TNB Library
TnbMfcEditHexData.h
[詳解]
1#pragma once
11#include "TnbMfcCommon.h"
12#include "TnbClipboard.h"
13#include "TnbBitmapImage.h"
14#include "TnbMfcBitmapDC.h"
15#include "TnbStrOperator.h"
16#include "TnbDummyCollection.h"
18#include "TnbFontHandle.h"
20#include <imm.h>
21#ifndef _WIN32_WCE
22 #pragma comment(lib,"imm32.lib")
23#endif
24
25
26
27//TNB Library
28namespace TNB {
29namespace MFC {
30
31
32
65template<int WIDTH = -1>
66class CEditHexDataT : public CWnd
67{
68 DEFSUPER(CWnd);
69public:
70
72 CEditHexDataT(void) : m_maxLength(-1), m_isInsertMode(false), m_isEnableNotify(false)
73 , m_selectCaretIndex(-1), m_isCaletVisidle(false), m_isShowCaretAlways(false)
74 {
75 ASSERT( WIDTH != 0 );
76 m_margin.x = 3;
77 m_margin.y = 2;
78 m_textColor = ::GetSysColor(COLOR_WINDOWTEXT);
79 m_backColor = ::GetSysColor(COLOR_WINDOW);
80 m_activeHighlightColor = ::GetSysColor(COLOR_HIGHLIGHT);
81 m_inactiveHighlightColor = ::GetSysColor(COLOR_BTNSHADOW);
82 m_hasCaret = false;
83 }
84
91 void SetMargins(const POINT& p)
92 {
93 m_margin = p;
94 m_Redraw();
95 }
96
103 void SetInsertMode(bool isEnable)
104 {
105 m_isInsertMode = isEnable;
106 m_Redraw();
107 }
108
115 bool IsInsertMode(void) const
116 {
117 return m_isInsertMode;
118 }
119
128 void SetLimitLength(int maxLength = -1, BYTE defaultData = 0)
129 {
130 m_maxLength = maxLength;
131 m_defaultData = defaultData;
132 m_SetData(CByteVector());
133 }
134
140 bool IsMultiLineMode(void) const
141 {
142 return WIDTH > 0;
143 }
144
149 const CByteVector& GetData(void) const
150 {
151 return m_data;
152 }
153
158 void SetData(const CByteVector& vb)
159 {
160 m_SetData(vb);
161 }
162
168 int GetVisibleLineCount(void) const
169 {
170 if ( IsMultiLineMode() )
171 {
172 CRect rc;
173 _super::GetClientRect(rc);
174 return (rc.Height() + m_charSize.cy - 1) / m_charSize.cy;
175 }
176 return 1;
177 }
178
184 int GetLineCount(void) const
185 {
186 if ( IsMultiLineMode() )
187 {
188 return (m_data.GetSize() + WIDTH - 1) / WIDTH;
189 }
190 return 1;
191 }
192
198 int GetFirstVisibleLine(void) const
199 {
200 if ( IsMultiLineMode() )
201 {
202 return m_viewPos.y / m_charSize.cy;
203 }
204 return 0;
205 }
206
212 void SetFirstVisibleLine(int line)
213 {
214 if ( IsMultiLineMode() )
215 {
216 int y = line;
217 int l = GetLineCount() - GetVisibleLineCount() + 1;
218 if ( y < 0 )
219 {
220 y = 0;
221 }
222 else if ( y > l )
223 {
224 y = l;
225 }
226 y *= m_charSize.cy;
227 if ( y != m_viewPos.y )
228 {
229 m_viewPos.y = y;
230 m_Redraw();
231 NotifyToParent(EN_VSCROLL);
232 }
233 }
234 }
235
241 void SetSel(int index)
242 {
243 m_ReleaseSelect();
244 m_SetCaretIndex(index);
245 m_Redraw();
246 }
247
254 void SetSel(int startIndex, int endIndex)
255 {
256 if ( startIndex == endIndex )
257 {
258 m_ReleaseSelect();
259 m_SetCaretIndex(startIndex);
260 m_Redraw();
261 return;
262 }
263 if ( endIndex < 0 )
264 {
265 endIndex = m_GetIndexMax();
266 }
267 m_ReleaseSelect();
268 m_SetCaretIndex(startIndex, false, true);
269 ASSERT( m_caretDrawPos.x >= 0 );
270 m_SetSelect(m_caretIndex, m_caretDrawPos);
271 m_SetCaretIndex(endIndex);
272 m_Redraw();
273 }
274
282 void GetSel(int& _startIndex, int& _endIndex) const
283 {
284 if ( m_selectCaretIndex < 0 )
285 {
286 // 未選択状態
287 _startIndex = m_caretIndex;
288 _endIndex = m_caretIndex;
289 }
290 else
291 {
292 // 選択状態
293 _startIndex = m_selectCaretIndex;
294 _endIndex = m_caretIndex;
295 }
296 }
297
305 void ReplaceSel(LPCTSTR lpszText)
306 {
307 CString s = lpszText;
308 if ( ! s.IsEmpty() )
309 {
310 bool nowInsertMode = m_isInsertMode;
311 if ( m_selectCaretIndex >= 0 )
312 {
313 m_isInsertMode = true;
314 }
315 m_isEnableNotify = false;
316 _super::SetRedraw(false);
317 s.MakeUpper(); // 大文字化
318 loop ( i, s.GetLength() )
319 {
320 m_Input(s.GetAt(i), false);
321 }
322 _super::SetRedraw(true);
323 m_isEnableNotify = true;
324 m_isInsertMode = nowInsertMode;
325 NotifyToParent(EN_SELCHANGE);
326 NotifyToParent(EN_CHANGE);
327 }
328 else
329 {
330 m_DeleteSelectedData();
331 m_ReleaseSelect();
332 }
333 m_Redraw();
334 }
335
342 void ReplaceSel(const CByteVector& vb)
343 {
345 }
346
353 bool AddToolTip(void)
354 {
355 if ( ::IsWindow(GetSafeHwnd()) )
356 {
357 m_toolTip.Create(this, TTS_ALWAYSTIP);
358 m_toolTip.AddTool(this, _T(""));
359 m_toolTip.Activate(TRUE);
360 return true;
361 }
362 return false;
363 }
364
370 {
371 m_isShowCaretAlways = true;
372 }
373
379 COLORREF SetTextColor(COLORREF color)
380 {
381 COLORREF r = m_textColor;
382 m_textColor = color;
383 m_Redraw();
384 return r;
385 }
386
392 COLORREF SetBkColor(COLORREF color)
393 {
394 COLORREF r = m_backColor;
395 m_backColor = color;
396 m_Redraw();
397 return r;
398 }
399
405 void SetHighlightColor(COLORREF activeColor, COLORREF inactiveColor)
406 {
407 m_activeHighlightColor = activeColor;
408 m_inactiveHighlightColor = inactiveColor;
409 }
410
419 static bool MakeContextMenu(CMenu& _menu, bool canCopy, int topMenuId)
420 {
421 if ( _menu.GetSafeHmenu() != NULL )
422 {
423 _menu.DestroyMenu();
424 }
425 BOOL r = TRUE;
426 r &= _menu.CreatePopupMenu();
427 CClipboard clipb;
428 bool canPaste = clipb.IsAvailable();
429 r &= _menu.AppendMenu(MF_STRING | (canCopy ? 0 : MF_GRAYED), topMenuId + 0, _T("切り取り(&T)"));
430 r &= _menu.AppendMenu(MF_STRING | (canCopy ? 0 : MF_GRAYED), topMenuId + 1, _T("コピー(&C)"));
431 r &= _menu.AppendMenu(MF_STRING | (canPaste ? 0 : MF_GRAYED), topMenuId + 2, _T("貼り付け(&P)"));
432 return !! r;
433 }
434
435protected:
436
443 virtual void PreSubclassWindow(void)
444 {
445 m_hasCaret = false;
446 ::ImmAssociateContext(_super::GetSafeHwnd(), NULL); // IME入力禁止
447 ::SetClassLong(_super::GetSafeHwnd(), GCL_HCURSOR, reinterpret_cast<LONG>(::LoadCursor(NULL, IDC_IBEAM)));
448 m_font.Set(_super::GetSafeHwnd());
449 m_SetData(CByteVector());
450 _super::PreSubclassWindow();
451 m_isEnableNotify = true;
452 m_CheckCharSize();
453 }
454
461 virtual BOOL PreTranslateMessage(MSG* pMsg)
462 {
463 if ( ::IsWindow(m_toolTip) )
464 {
465 m_toolTip.RelayEvent(pMsg);
466 }
467 return _super::PreTranslateMessage(pMsg);
468 }
469
479 virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
480 {
481 switch ( message )
482 {
483 case WM_DESTROY:
484 m_toolTip.DestroyWindow();
485 m_isEnableNotify = false;
486 break;
487 case WM_SETFONT:
488 {
489 HFONT hFont = reinterpret_cast<HFONT>(wParam);
490 if ( hFont != NULL )
491 {
492 m_font.SetClone(hFont);
493 m_CheckCharSize();
494 if ( LOWORD(lParam) != 0 )
495 {
496 m_Redraw();
497 }
498 }
499 }
500 break;
501 case WM_PAINT:
502 m_DrawClient(CPaintDC(this));
503 return 0;
504 break;
505 case WM_SETTEXT:
506 m_OnSetText(reinterpret_cast<LPCTSTR>(lParam));
507 return 1;
508 break;
509 case WM_GETTEXTLENGTH:
510 if ( m_dataString.GetLength() > 0 )
511 {
512 return (m_dataString.GetLength() - 1) * sizeof(TCHAR);
513 }
514 return 0;
515 break;
516 case WM_GETTEXT:
517 if ( wParam > 0 && m_dataString.GetLength() > 0 )
518 {
519 LPTSTR pDst = reinterpret_cast<TCHAR*>(lParam);
520 LPCTSTR pSrc = m_dataString;
521 size_t n = m_dataString.GetLength() - 1; //最後はSPだから
522 size_t m = min(wParam, n);
523 loop ( i, m )
524 {
525 *pDst++ = *pSrc++;
526 }
527 *pDst = 0;
528 return m * sizeof(TCHAR);
529 }
530 return 0;
531 break;
532 case WM_SETFOCUS:
533 m_Redraw();
534 NotifyToParent(EN_SETFOCUS);
535 return 0;
536 break;
537 case WM_KILLFOCUS:
538 m_HideCaret();
539 m_Redraw();
540 NotifyToParent(EN_KILLFOCUS);
541 return 0;
542 break;
543 case WM_KEYDOWN:
544 return m_OnChar(wParam, lParam);
545 case WM_KEYUP:
546 case WM_CHAR:
547 return 0;
548 case WM_RBUTTONDOWN:
549 case WM_RBUTTONUP:
550 _super::SetFocus();
551 break;
552 case WM_LBUTTONDOWN:
553 case WM_LBUTTONUP:
554 case WM_MOUSEMOVE:
555 return m_OnMouse(message, wParam, lParam);
556 break;
557 case WM_MOUSEWHEEL:
558 {
559 short d = HIWORD(wParam);
561 }
562 break;
563 case WM_ERASEBKGND:
564 if ( IsMultiLineMode() )
565 {
566 return 0;
567 }
568 if ( IsWindowEnabled() )
569 {
570 HDC hdc = reinterpret_cast<HDC>(wParam);
571 CRect rect;
572 GetClientRect(rect);
573 CBrush b(m_backColor);
574 ::FillRect(hdc, &rect, b);
575 return 0;
576 }
577 break;
578 case WM_ENABLE:
579 {
580 CWnd* pParent = GetParent();
581 if ( pParent != NULL )
582 {
583 CRect rect;
584 GetClientRect(rect);
585 ClientToScreen(rect);
586 pParent->ScreenToClient(rect);
587 pParent->InvalidateRect(rect, TRUE);
588 }
589 Invalidate(TRUE);
590 }
591 return 0;
592 break;
593 case WM_GETDLGCODE:
594 return DLGC_WANTCHARS | DLGC_WANTARROWS;
595 break;
596 case WM_COPY:
597 case WM_CUT:
598 if ( m_selectCaretIndex >= 0 && m_caretIndex != m_selectCaretIndex )
599 {
600 CClipboard clipb;
601 int x1 = m_GetCaretIndex() / 2;
602 int x2 = m_selectCaretIndex / 2;
603 CStr s = CStrOperator::BinaryToHexString(m_data.Mid(min(x1, x2), ::abs(x1 - x2)));
604 clipb.SetString(s);
605 if ( message == WM_CUT )
606 {
607 m_DeleteSelectedData();
608 m_ReleaseSelect();
609 m_Redraw();
610 }
611 return 1;
612 }
613 return 0;
614 break;
615 case WM_PASTE:
616 ReplaceSel(CClipboard().GetString());
617 return 1;
618 break;
619 case WM_CONTEXTMENU:
620 {
621 CMenu menu;
622 bool canCopy = (m_selectCaretIndex >= 0);
623 if ( MakeContextMenu(menu, canCopy, 100) )
624 {
625 CPoint po(lParam);
626 if ( po.x == -1 && po.y == -1 )
627 {
628 po = _super::GetCaretPos();
629 if ( po.x < 0 )
630 {
631 ::GetCursorPos(&po);
632 }
633 else
634 {
635 _super::ClientToScreen(&po);
636 po.y += m_charSize.cy;
637 }
638 }
639 TrackPopupMenuEx(menu, 0, po.x, po.y, _super::GetSafeHwnd(), NULL);
640 }
641 return 0;
642 }
643 break;
644 case WM_COMMAND:
645 {
646 switch ( LOWORD(wParam) )
647 {
648 case 100:
649 SendMessage(WM_CUT);
650 break;
651 case 101:
652 SendMessage(WM_COPY);
653 break;
654 case 102:
655 SendMessage(WM_PASTE);
656 break;
657 }
658 }
659 break;
660 default:
661 break;
662 }
663 return _super::WindowProc(message, wParam, lParam);
664 }
665
671 virtual void NotifyToParent(WORD notifyCode)
672 {
673 if ( m_isEnableNotify )
674 {
675 MFCLIB::SendCommandMessage(this, notifyCode);
676 }
677 }
678
683 COLORREF GetTextColor(void) const
684 {
685 return IsWindowEnabled() ? m_textColor : ::GetSysColor(COLOR_GRAYTEXT);
686 }
687
692 COLORREF GetBkColor(void) const
693 {
694 return IsWindowEnabled() ? m_backColor : ::GetSysColor(COLOR_MENU);
695 }
696
697private:
698 // 再表示
699 void m_Redraw(void)
700 {
701 _super::Invalidate();
702 }
703
704 // 文字の大きさチェック
705 void m_CheckCharSize(void)
706 {
707 CClientDC dc(this);
708 HGDIOBJ hOld = ::SelectObject(dc, m_font);
709 m_charSize = dc.GetTextExtent(_T("8"));
710 ::SelectObject(dc, hOld);
711 }
712
718 int m_GetIndexMax(void) const
719 {
720 return m_data.GetSize() * 2;
721 }
722
728 void m_OnSetText(LPCTSTR lpsz)
729 {
730 m_SetData(CStrOperator::HexStringToBinary(lpsz));
731 }
732
738 void m_SetData(const CByteVector& vb)
739 {
740 m_data = vb;
741 if ( m_maxLength > 0 && ToInt(m_data.GetSize()) > m_maxLength )
742 {
743 m_data.SetSize(m_maxLength);
744 }
745 m_MakeViewData();
746 m_viewPos.x = 0;
747 m_viewPos.y = 0;
748 m_SetCaretIndex(0);
749 m_ReleaseSelect();
750 m_Redraw();
751 NotifyToParent(EN_SELCHANGE);
752 NotifyToParent(EN_CHANGE);
753 NotifyToParent(EN_VSCROLL);
754 NotifyToParent(EN_HSCROLL);
755 }
756
763 void m_SetCaretIndex(int p, bool isNotify = true, bool isCalcDrawPos = false)
764 {
765 if ( p < 0 )
766 {
767 p = 0;
768 }
769 int im = m_GetIndexMax();
770 if ( p > im )
771 {
772 p = im;
773 }
774 bool r = (m_caretIndex != p);
775 if ( r )
776 {
777 m_caretIndex = p;
778 m_caretDrawPos.x = -1;
779 }
780 if ( isCalcDrawPos && m_caretDrawPos.x < 0 )
781 {
782 CClientDC dc(this);
783 HGDIOBJ hOld = ::SelectObject(dc, m_font);
784 m_caretDrawPos = m_IndexToClientPoint(dc, m_caretIndex);
785 ::SelectObject(dc, hOld);
786 }
787 if ( r )
788 {
789 m_isCaletVisidle = true;
790 if ( isNotify )
791 {
792 NotifyToParent(EN_SELCHANGE);
793 }
794 }
795 }
796
797 // カレットのインデックス取得
798 int m_GetCaretIndex(void) const
799 {
800 return m_caretIndex;
801 }
802
810 LRESULT m_OnMouse(UINT message, WPARAM wParam, LPARAM lParam)
811 {
812 bool isCaptrued = (::GetCapture() == _super::GetSafeHwnd());
813 if ( message == WM_LBUTTONUP )
814 {
815 // UP
816 if ( isCaptrued )
817 {
818 ::ReleaseCapture();
819 if ( m_selectCaretIndex == m_GetCaretIndex() )
820 {
821 m_ReleaseSelect();
822 m_Redraw();
823 }
824 }
825 return 0;
826 }
827 if ( message == WM_MOUSEMOVE && ! isCaptrued )
828 {
829 return 0;
830 }
831 CPoint po(lParam);
832 CClientDC dc(this);
833 HGDIOBJ hOld = ::SelectObject(dc, m_font);
834 int l = m_ClientPointToIndex(dc, po);
835 ::SelectObject(dc, hOld);
836 if ( message == WM_LBUTTONDOWN )
837 {
838 bool isShift = (::GetAsyncKeyState(VK_SHIFT) < 0);
839 if ( m_selectCaretIndex < 0 )
840 {
841 if ( isShift )
842 {
843 m_SetSelect(m_caretIndex, m_caretDrawPos);
844 ::SetCapture(_super::GetSafeHwnd());
845 }
846 }
847 else
848 {
849 if ( ! isShift )
850 {
851 m_ReleaseSelect();
852 }
853 }
854 }
855 m_SetCaretIndex(l, true, true);
856 if ( ! isCaptrued )
857 {
858 CPoint spo = po - m_margin;
859 _super::ClientToScreen(&spo);
860 if ( ::DragDetect(m_hWnd, spo) )
861 {
862 // プレス!
863 m_SetSelect(m_caretIndex, m_caretDrawPos);
864 ::SetCapture(_super::GetSafeHwnd());
865 }
866 }
867 _super::SetFocus();
868 m_Redraw();
869 return 0;
870 }
871
878 LRESULT m_OnChar(WPARAM wParam, LPARAM lParam)
879 {
880 if ( (lParam & _BIT(31)) != 0 )
881 {
882 //離された時はなにもすることがない。
883 return 0;
884 }
885 bool isShift = (::GetAsyncKeyState(VK_SHIFT) < 0);
886 bool isCtrl = (::GetAsyncKeyState(VK_CONTROL) < 0);
887 //
888 if ( isShift && wParam == VK_INSERT )
889 {
890 isShift = false;
891 isCtrl = true;
892 wParam = 'V';
893 }
894 if ( isCtrl )
895 {
896 switch ( wParam )
897 {
898 case 'A':
899 SetSel(0, -1);
900 break;
901 case 'C':
902 SendMessage(WM_COPY);
903 break;
904 case 'X':
905 SendMessage(WM_CUT);
906 break;
907 case 'V':
908 SendMessage(WM_PASTE);
909 break;
910 default:
911 break;
912 }
913 return 0;
914 }
915 m_Input(wParam, isShift);
916 return 0;
917 }
918
924 void m_Input(WPARAM ch, bool isShift)
925 {
926 bool isWork = true;
927 bool isSendChange = false;
928 int nowPosition = m_GetCaretIndex();
929 POINT nowDrawPos = m_caretDrawPos;
930 //
931 if ( ! IsMultiLineMode() )
932 {
933 // SingleLine
934 switch( ch )
935 {
936 case VK_UP:
937 case VK_PRIOR:
938 ch = VK_HOME;
939 break;
940 case VK_DOWN:
941 case VK_NEXT:
942 ch = VK_END;
943 break;
944 }
945 }
946 //
947 switch ( ch )
948 {
949 case VK_INSERT:
950 m_isInsertMode = ! m_isInsertMode;
951 NotifyToParent(EN_SELCHANGE);
952 isWork = false;
953 if ( m_hasCaret )
954 {
955 POINT p = _super::GetCaretPos();
956 if ( m_isInsertMode )
957 {
958 _super::CreateSolidCaret(2, m_charSize.cy);
959 }
960 else
961 {
962 _super::CreateSolidCaret(m_charSize.cx, m_charSize.cy);
963 }
964 _super::ShowCaret();
965 _super::SetCaretPos(p);
966 }
967 break;
968 case VK_DELETE:
969 if ( ! m_DeleteSelectedData() )
970 {
971 int x = m_GetCaretIndex() / 2;
972 m_SetCaretIndex(x * 2);
973 m_data.Remove(x);
974 m_MakeViewData();
975 isSendChange = true;
976 }
977 else
978 {
979 m_ReleaseSelect();
980 }
981 isShift = false;
982 break;
983 case VK_BACK:
984 if ( ! m_DeleteSelectedData() )
985 {
986 if ( m_GetCaretIndex() == 0 )
987 {
988 break;
989 }
990 int x = (m_GetCaretIndex() - 1) / 2;
991 m_SetCaretIndex(x * 2);
992 m_data.Remove(x);
993 m_MakeViewData();
994 isSendChange = true;
995 }
996 else
997 {
998 m_ReleaseSelect();
999 }
1000 isShift = false;
1001 break;
1002 case VK_HOME:
1003 m_SetCaretIndex(0);
1004 break;
1005 case VK_END:
1006 m_SetCaretIndex(m_GetIndexMax());
1007 break;
1008 case VK_PRIOR:
1009 case VK_NEXT:
1010 {
1011 int s = ((nowPosition & 1) == 0) ? 0 : 1;
1012 int w = WIDTH * 2 * (GetVisibleLineCount() - 1);
1013 if ( ch == VK_PRIOR )
1014 {
1015 w = -w;
1016 }
1017 int n = nowPosition + w + s;
1018 m_SetCaretIndex(n);
1019 }
1020 break;
1021 case VK_UP:
1022 {
1023 int s = ((nowPosition & 1) == 0) ? 0 : 1;
1024 int n = nowPosition - WIDTH * 2 - s;
1025 if ( n >= 0 )
1026 {
1027 m_SetCaretIndex(n);
1028 }
1029 }
1030 break;
1031 case VK_DOWN:
1032 {
1033 int s = ((nowPosition & 1) == 0) ? 0 : 1;
1034 int n = nowPosition + WIDTH * 2 + s;
1035 if ( n < m_GetIndexMax() )
1036 {
1037 m_SetCaretIndex(n);
1038 }
1039 }
1040 break;
1041 case VK_RIGHT:
1042 if ( ! isShift && m_selectCaretIndex >= 0 )
1043 {
1044 // 選択状態
1045 if ( m_selectCaretIndex < nowPosition )
1046 {
1047 break;
1048 }
1049 }
1050 if ( m_GetIndexMax() > nowPosition )
1051 {
1052 int s = ((nowPosition & 1) == 0) ? 2 : 1;
1053 m_SetCaretIndex(nowPosition + s);
1054 }
1055 break;
1056 case VK_LEFT:
1057 if ( ! isShift && m_selectCaretIndex >= 0 )
1058 {
1059 // 選択状態
1060 if ( m_selectCaretIndex > nowPosition )
1061 {
1062 break;
1063 }
1064 }
1065 if ( nowPosition > 0 )
1066 {
1067 int s = ((nowPosition & 1) == 0) ? 2 : 1;
1068 m_SetCaretIndex(nowPosition - s);
1069 }
1070 break;
1071 default:
1072 if ( isShift )
1073 {
1074 isWork = false;
1075 }
1076 else
1077 {
1078 int c = -1;
1079 if ( ch >= VK_NUMPAD0 && ch <= VK_NUMPAD9 )
1080 {
1081 c = ch - VK_NUMPAD0;
1082 }
1083 else
1084 {
1085 c = STRLIB::HexCharToInt(ch);
1086 }
1087 if ( c < 0 )
1088 {
1089 isWork = false;
1090 }
1091 else
1092 {
1093 bool isDeleted = m_DeleteSelectedData();
1094 bool isLead = ((m_GetCaretIndex() & 1) == 0);
1095 INDEX x = m_GetCaretIndex() / 2;
1096 if ( m_data.GetSize() <= x )
1097 {
1098 //末にある
1099 if ( m_maxLength > 0 && m_maxLength <= ToInt(m_data.GetSize()) )
1100 {
1101 break;
1102 }
1103 else
1104 {
1105 x = m_data.GetSize();
1106 m_data.SetSize(x + 1);
1107 m_data[x] = static_cast<BYTE>(c << 4);
1108 m_MakeViewData();
1109 isSendChange = true;
1110 }
1111 }
1112 else if ( isLead )
1113 {
1114 if ( m_isInsertMode || isDeleted )
1115 {
1116 if ( IsMultiLineMode() && m_maxLength > 0 )
1117 {
1118 // マルチライン&リミット
1119 m_data.Insert(x, static_cast<BYTE>(c << 4));
1120 m_MakeViewData();
1121 isSendChange = true;
1122 }
1123 else
1124 {
1125 if ( m_maxLength > 0 && m_maxLength <= ToInt(m_data.GetSize()) )
1126 {
1127 break;
1128 }
1129 else
1130 {
1131 m_data.Insert(x, static_cast<BYTE>(c << 4));
1132 m_MakeViewData();
1133 isSendChange = true;
1134 }
1135 }
1136 }
1137 else
1138 {
1139 m_data[x] &= 0x0F;
1140 m_data[x] |= static_cast<BYTE>(c << 4);
1141 m_MakeViewData();
1142 isSendChange = true;
1143 }
1144 }
1145 else
1146 {
1147 m_data[x] &= 0xF0;
1148 m_data[x] |= static_cast<BYTE>(c);
1149 m_MakeViewData();
1150 isSendChange = true;
1151 }
1152 m_SetCaretIndex(m_GetCaretIndex() + 1);
1153 }
1154 }
1155 break;
1156 }
1157 if ( isWork )
1158 {
1159 if ( isShift && m_selectCaretIndex < 0 )
1160 {
1161 m_SetSelect(nowPosition, nowDrawPos);
1162 }
1163 if ( ! isShift && m_selectCaretIndex >= 0 )
1164 {
1165 m_ReleaseSelect();
1166 }
1167 m_Redraw();
1168 }
1169 if ( isSendChange )
1170 {
1171 NotifyToParent(EN_CHANGE);
1172 }
1173 }
1174
1178 int m_ClientPointToIndex(CDC& dc, const POINT& point)
1179 {
1180 CPoint po = point;
1181 po = po - m_margin + m_viewPos;
1182 if ( po.x < 0 )
1183 {
1184 po.x = 0;
1185 }
1186 if ( po.y < 0 )
1187 {
1188 po.y = 0;
1189 }
1190 int w = (po.x) / m_charSize.cx;
1191 int h = (po.y) / m_charSize.cy;
1192 if ( IsMultiLineMode() )
1193 {
1194 //== Multi Line
1195 w = w / 3 * 2;
1196 if ( w > WIDTH * 2 )
1197 {
1198 w = WIDTH * 2;
1199 }
1200 return w + h * (WIDTH * 2);
1201 }
1202 //== Single Line
1203 while ( m_dataString.GetLength() > w )
1204 {
1205 if ( po.x < dc.GetTextExtent(m_dataString.Left(w + 1)).cx )
1206 {
1207 break;
1208 }
1209 w++;
1210 }
1211 w = w / 3 * 2;
1212 if ( w > m_GetIndexMax() )
1213 {
1214 w = m_GetIndexMax();
1215 }
1216 return w;
1217 }
1218
1220 CPoint m_IndexToClientPoint(CDC& dc, int index)
1221 {
1222 CPoint pos;
1223 if ( IsMultiLineMode() )
1224 {
1225 //== MultiLine
1226 int x = index % (WIDTH * 2);
1227 pos.x = (x + (x / 2)) * m_charSize.cx;
1228 pos.y = (index / (WIDTH * 2)) * m_charSize.cy;
1229 if ( m_maxLength > 0 )
1230 {
1231 //リミット有り
1232 if ( index == m_GetIndexMax() )
1233 {
1234 pos.x = (WIDTH * 3) * m_charSize.cx;
1235 pos.y -= m_charSize.cy;
1236 }
1237 }
1238 }
1239 else
1240 {
1241 //== SingleLine
1242 int l = index + (index / 2);
1243 CPoint p = dc.GetTextExtent(m_dataString.Left(l));
1244 pos.x = p.x;
1245 pos.y = 0;
1246 }
1247 return pos;
1248 }
1249
1256 bool m_DeleteSelectedData(void)
1257 {
1258 if ( m_selectCaretIndex >= 0 && m_caretIndex != m_selectCaretIndex )
1259 {
1260 int x1 = m_GetCaretIndex() / 2;
1261 int x2 = m_selectCaretIndex / 2;
1262 m_data.RemoveElements(min(x1, x2), ::abs(x1 - x2));
1263 m_MakeViewData();
1264 if ( m_GetCaretIndex() > m_selectCaretIndex )
1265 {
1266 m_SetCaretIndex(m_selectCaretIndex);
1267 }
1268 return true;
1269 }
1270 return false;
1271 }
1272
1277 void m_MakeViewData(void)
1278 {
1279 if ( IsMultiLineMode() && m_maxLength > 0 )
1280 {
1281 // マルチライン&リミット
1282 if ( ToInt(m_data.GetSize()) > m_maxLength )
1283 {
1284 m_data.SetSize(m_maxLength);
1285 }
1286 CDummyCollectionT<BYTE> dc(m_defaultData);
1287 dc.SetSize(m_maxLength - m_data.GetSize());
1288 m_data.Append(dc);
1289 ASSERT( ToInt(m_data.GetSize()) == m_maxLength );
1290 }
1291 //
1292 TCHAR* P = m_dataString.GetBuffer(m_data.GetSize() * 3 + 1);
1293 loop ( i, m_data )
1294 {
1295 BYTE b = m_data[i];
1296 *P++ = STRLIB::IntToHexChar(b >> 4);
1297 *P++ = STRLIB::IntToHexChar(b & 0x0F);
1298 *P++ = ' ';
1299 }
1300 *P = '\0';
1301 m_dataString.ReleaseBuffer();
1302 if ( ::IsWindow(m_toolTip) )
1303 {
1304 m_toolTip.UpdateTipText(CStr::Fmt(_T("has %d byte(s)."), m_data.GetSize()), this);
1305 }
1306// NotifyToParent(EN_CHANGE);
1307 }
1308
1313 void m_DrawClient(CDC& dc)
1314 {
1315 CPoint nowPos = m_viewPos;
1316 CRect rc;
1317 GetClientRect(rc);
1318 HGDIOBJ hOld = ::SelectObject(dc, m_font);
1319 dc.IntersectClipRect(rc);
1320 if ( m_caretDrawPos.x < 0 )
1321 {
1322 m_caretDrawPos = m_IndexToClientPoint(dc, m_caretIndex);
1323 }
1324 dc.SetBkMode(TRANSPARENT);
1325 if ( IsMultiLineMode() )
1326 {
1327 m_DrawMultiLineMode(dc, rc);
1328 }
1329 else
1330 {
1331 m_DrawSingleLineMode(dc, rc);
1332 }
1333 ::SelectObject(dc, hOld);
1334 //
1335 if ( m_HasFocus() )
1336 {
1337 CPoint p = m_caretDrawPos - m_viewPos;
1338 if ( rc.PtInRect(p) && rc.PtInRect(p + m_charSize) )
1339 {
1340 p.x--;
1341 }
1342 else
1343 {
1344 p.x = 60000;
1345 }
1346 _super::SetCaretPos(p + m_margin);
1347 if ( ! m_hasCaret )
1348 {
1349 m_hasCaret = true;
1350 if ( m_isInsertMode )
1351 {
1352 _super::CreateSolidCaret(2, m_charSize.cy);
1353 }
1354 else
1355 {
1356 _super::CreateSolidCaret(m_charSize.cx, m_charSize.cy);
1357 }
1358 _super::ShowCaret();
1359 _super::SetCaretPos(p + m_margin);
1360 }
1361 }
1362 if ( nowPos.x != m_viewPos.x )
1363 {
1364 NotifyToParent(EN_HSCROLL);
1365 }
1366 if ( nowPos.y != m_viewPos.y )
1367 {
1368 NotifyToParent(EN_VSCROLL);
1369 }
1370 }
1371
1377 void m_DrawMultiLineMode(CDC& targetDC, const CRect& clientRect)
1378 {
1379 CRect rc = clientRect;
1380 rc.left += m_margin.x;
1381 rc.top += m_margin.y;
1382 //== 表示位置補正
1383 if ( m_isCaletVisidle )
1384 {
1385 m_isCaletVisidle = false;
1386 CPoint p = m_IndexToClientPoint(targetDC, m_caretIndex);
1387 if ( rc.Width() - m_charSize.cx < p.x - m_viewPos.x )
1388 {
1389 m_viewPos.x = p.x - (rc.Width() - m_charSize.cx);
1390 }
1391 if ( p.x < m_viewPos.x )
1392 {
1393 m_viewPos.x = p.x;
1394 }
1395 int hh = rc.Height() / m_charSize.cy * m_charSize.cy;
1396 if ( hh - m_charSize.cy < p.y - m_viewPos.y )
1397 {
1398 m_viewPos.y = p.y - (hh - m_charSize.cy);
1399 }
1400 if ( p.y < m_viewPos.y )
1401 {
1402 m_viewPos.y = p.y;
1403 }
1404 }
1405 CBitmapImage bi;
1406 bi.Set(clientRect.Width(), clientRect.Height(), GetBkColor());
1407 //== 裏画面で画像作成
1408 {
1409 CBitmapDC dc(&bi);
1410 CDcSelectAssistant dca(dc);
1411 dc.SetWindowOrg(m_viewPos);
1412 dca.SelectFont(m_font);
1413 dca.SetTextColor(GetTextColor());
1414 dca.SetBkColor(GetBkColor());
1415 //== 文字表示
1416 rc.right += m_viewPos.x;
1417 rc.bottom = rc.top + m_charSize.cy;
1418 int d = WIDTH * 3;
1419 loop ( i, m_dataString.GetLength() / d + 1 )
1420 {
1421 if ( dc.RectVisible(rc) )
1422 {
1423 CString ss = m_dataString.Mid(i * d, d);
1424 dc.DrawText(ss, rc, DT_LEFT);
1425 }
1426 rc.top += m_charSize.cy;
1427 rc.bottom += m_charSize.cy;
1428 }
1429 //== 選択表示
1430 bool hasFocus = m_HasFocus();
1431 if ( m_selectCaretIndex >= 0 && m_selectCaretIndex != m_caretIndex )
1432 {
1433 POINT p1 = m_selectCaretDrawPos;
1434 POINT p2 = m_caretDrawPos;
1435 if ( p1.y == p2.y )
1436 {
1437 if ( p1.x > p2.x )
1438 {
1439 Swap(p1.x, p2.x);
1440 }
1441 CRect rc(p1.x, p1.y, p2.x - m_charSize.cx, p1.y + m_charSize.cy);
1442 m_DrawSelectMark(dc, rc + m_margin, hasFocus);
1443 }
1444 else
1445 {
1446 if ( p1.y > p2.y )
1447 {
1448 Swap(p1, p2);
1449 }
1450 loop ( i, (p2.y - p1.y) / m_charSize.cy - 1 )
1451 {
1452 CPoint ps(0, p1.y + (i + 1) * m_charSize.cy);
1453 CSize sz(m_charSize.cx * (WIDTH * 3 - 1), m_charSize.cy);
1454 m_DrawSelectMark(dc, CRect(ps, sz) + m_margin, hasFocus);
1455 }
1456 CRect rc1(p1.x, p1.y, m_charSize.cx * (WIDTH * 3 - 1), p1.y + m_charSize.cy);
1457 m_DrawSelectMark(dc, rc1 + m_margin, hasFocus);
1458 CRect rc2(0, p2.y, p2.x - m_charSize.cx, p2.y + m_charSize.cy);
1459 m_DrawSelectMark(dc, rc2 + m_margin, hasFocus);
1460 }
1461 }
1462 else if ( m_isShowCaretAlways && ! hasFocus )
1463 {
1464 CRect rc(m_caretDrawPos, m_charSize);
1465 if ( m_isInsertMode )
1466 {
1467 rc.right = rc.left + 1;
1468 }
1469 rc.left--;
1470 rc += m_margin;
1471 m_DrawSelectMark(dc, rc, false);
1472 }
1473 }
1474 bi.Draw(targetDC, 0, 0);
1475 }
1476
1482 void m_DrawSingleLineMode(CDC& dc, const CRect& clientRect)
1483 {
1484 CRect rc = clientRect;
1485 rc.left += m_margin.x;
1486 rc.top += m_margin.y;
1487 //== 表示位置補正
1488 if ( m_isCaletVisidle )
1489 {
1490 m_isCaletVisidle = false;
1491 CPoint p = m_IndexToClientPoint(dc, m_caretIndex);
1492 if ( rc.Width() - m_charSize.cx < p.x - m_viewPos.x )
1493 {
1494 m_viewPos.x = (p.x - (rc.Width() - m_charSize.cx));
1495 }
1496 if ( p.x < m_viewPos.x )
1497 {
1498 m_viewPos.x = p.x;
1499 }
1500 m_viewPos.y = 0;
1501 }
1502 dc.SetWindowOrg(m_viewPos);
1503 //== 文字表示
1504 rc.right += m_viewPos.x;
1505 dc.SetTextColor(GetTextColor());
1506 dc.SetBkColor(GetBkColor());
1507 dc.DrawText(m_dataString, rc, DT_LEFT);
1508 //== 選択表示
1509 if ( m_selectCaretIndex >= 0 && m_selectCaretIndex != m_caretIndex )
1510 {
1511 int x1 = m_selectCaretDrawPos.x;
1512 int x2 = m_caretDrawPos.x;
1513 if ( x1 > x2 )
1514 {
1515 Swap(x1, x2);
1516 }
1517 CRect rc(x1, 0, x2 - m_charSize.cx + 2, m_charSize.cy);
1518 m_DrawSelectMark(dc, rc + m_margin);
1519 }
1520 else if ( m_isShowCaretAlways && ! m_HasFocus() )
1521 {
1522 CRect rc(m_caretDrawPos, m_charSize);
1523 if ( m_isInsertMode )
1524 {
1525 rc.right = rc.left + 1;
1526 }
1527 rc.left--;
1528 rc += m_margin;
1529 ::DrawFocusRect(dc, &rc);
1530 }
1531 }
1532
1538 void m_DrawSelectMark(CDC& dc, const CRect& rect, bool isActive = true)
1539 {
1540 COLORREF color = isActive ? m_activeHighlightColor : m_inactiveHighlightColor;
1541 CSelectedBeltDrawer d(rect.Size(), color, GetBkColor(), isActive);
1542 d.Draw(dc, rect.left, rect.top);
1543 }
1544
1545 void m_SetSelect(int index, const POINT& drawPos)
1546 {
1547 m_selectCaretIndex = index;
1548 m_selectCaretDrawPos = drawPos;
1549 if ( (index & 1) != 0 )
1550 {
1551 // 奇数なら
1552 m_selectCaretIndex--;
1553 m_selectCaretDrawPos.x -= m_charSize.cx;
1554 }
1555 }
1556
1557 void m_ReleaseSelect(void)
1558 {
1559 if ( m_selectCaretIndex >= 0 )
1560 {
1561 m_selectCaretIndex = -1;
1562 }
1563 }
1564
1565 void m_HideCaret(void)
1566 {
1567 m_hasCaret = false;
1568 _super::HideCaret();
1569// ::DestroyCaret();
1570 }
1571
1572 bool m_HasFocus(void) const
1573 {
1574 return (::GetFocus() == _super::GetSafeHwnd());
1575 }
1576
1577 // 表示関係
1578 CFontHandle m_font;
1579 CSize m_charSize;
1580 CPoint m_margin;
1581 CToolTipCtrl m_toolTip;
1582 COLORREF m_textColor;
1583 COLORREF m_backColor;
1584 COLORREF m_activeHighlightColor;
1585 COLORREF m_inactiveHighlightColor;
1586 // 状態関係
1587 bool m_isInsertMode;
1588 int m_maxLength;
1589 bool m_isEnableNotify;
1590 // データ関係
1591 CByteVector m_data;
1592 CString m_dataString;
1593 BYTE m_defaultData;
1594 // カレット関係
1595 int m_caretIndex;
1596 CPoint m_caretDrawPos;
1597 int m_selectCaretIndex;
1598 CPoint m_selectCaretDrawPos;
1599 bool m_isShowCaretAlways;
1600 bool m_hasCaret;
1601 // スクロール関係
1602 bool m_isCaletVisidle;
1603 CPoint m_viewPos;
1604};
1605
1606
1607
1625{
1626};
1627
1628
1629
1650{
1651};
1652
1653
1654
1655}; //MFC
1656}; //TNB
ビットマップイメージ管理関係のヘッダ
Windowsクリップボード関係のヘッダ
デバイステキストセレクトアシスタント関係のヘッダ
#define _BIT(X)
BIT演算
Definition: TnbDef.h:307
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
ダミーコレクション関係のヘッダ
フォントハンドル関係のヘッダ
ビットマップDC関係のヘッダ
MFCコントロール共通のヘッダ
選択帯描画情報のヘッダ
文字列操作関係のヘッダ
ウィンドウ管理.
HWND GetSafeHwnd(void) const
[取得] ウィンドウハンドル取得.
ビットマップイメージ管理クラス
bool Set(int cx, int cy, COLORREF color=CLR_INVALID)
[設定] イメージ設定.
bool Draw(HDC hdc, int x=0, int y=0) const
[処理] イメージ描画.
クリップボードアクセスクラス
Definition: TnbClipboard.h:49
bool IsAvailable(UINT uFormat=0) const
[確認] 存在確認.
Definition: TnbClipboard.h:98
bool SetString(LPCTSTR lpszText, bool isAdd=false)
[設定] 文字列登録.
Definition: TnbClipboard.h:174
デバイステキストセレクトアシスタント
HFONT型ハンドルハンドル
Definition: TnbFontHandle.h:80
bool Set(const LOGFONT &attr)
[設定] フォント設定.
bool SetClone(HFONT hFont, double mul=1.0)
[設定] フォント設定.
選択帯描画クラス
static CStrT< TYP > BinaryToHexString(const IConstCollectionT< BYTE > &c)
[作成] バイナリ→HEX文字列
static CByteVector HexStringToBinary(const TYP *lpszHex)
[作成] HEX文字列→バイナリ
static CStrT Fmt(const TCHAR *lpszFormat,...)
[作成] 書式付き文字列作成
Definition: TnbStr.h:1206
virtual size_t GetSize(void) const
[取得] サイズ取得
Definition: TnbVector.h:368
virtual bool Insert(INDEX index, const TYP &t)
[追加] 要素一つ挿入
Definition: TnbVector.h:579
virtual size_t RemoveElements(INDEX index, size_t size=0)
[削除] 要素削除.
Definition: TnbVector.h:409
virtual bool Remove(INDEX index)
[削除] 要素一つ削除.
Definition: TnbVector.h:397
virtual bool SetSize(size_t size)
[操作] サイズ指定
Definition: TnbVector.h:618
CVectorT< TYP > Mid(INDEX startIndex, size_t size=0) const
[作成] 切り出し
Definition: TnbVector.h:705
virtual size_t Append(const IConstCollectionT< TYP > &c)
[追加] 追加.
Definition: TnbVector.h:545
ビットマップデバイスコンテキストクラス
マルチラインHEXデータ入力Editコントロール
HEXデータ入力Editコントロールテンプレート
void SetHighlightColor(COLORREF activeColor, COLORREF inactiveColor)
[設定] ハイライト色設定.
void ReplaceSel(const CByteVector &vb)
[置換] データ置換.
void SetSel(int index)
[設定] 選択位置設定.
COLORREF GetTextColor(void) const
[取得] 文字色取得.
static bool MakeContextMenu(CMenu &_menu, bool canCopy, int topMenuId)
[作成] コンテキストメニュー作成.
const CByteVector & GetData(void) const
[取得] 入力データ取得.
COLORREF GetBkColor(void) const
[取得] 背景色取得.
bool AddToolTip(void)
[設定] ツールチップ追加.
bool IsInsertMode(void) const
[取得] インサートモード取得.
COLORREF SetBkColor(COLORREF color)
[設定] 背景色設定.
void SetLimitLength(int maxLength=-1, BYTE defaultData=0)
[設定] 最大長設定.
CEditHexDataT(void)
コンストラクタ.
int GetLineCount(void) const
[取得] 行数取得.
virtual void PreSubclassWindow(void)
[通知] subclassing/unsubclassing functions.
void SetMargins(const POINT &p)
[設定] マージン設定.
int GetVisibleLineCount(void) const
[取得] 可視行数取得.
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
[通知] for processing Windows messages.
virtual BOOL PreTranslateMessage(MSG *pMsg)
[通知] for translating Windows messages in main message pump
void SetData(const CByteVector &vb)
[設定] データ設定.
void GetSel(int &_startIndex, int &_endIndex) const
[取得] 選択位置取得.
bool IsMultiLineMode(void) const
[取得] マルチライン確認.
void SetFirstVisibleLine(int line)
[設定] 可視最上行設定.
int GetFirstVisibleLine(void) const
[取得] 可視最上行取得.
COLORREF SetTextColor(COLORREF color)
[設定] 文字色設定.
virtual void NotifyToParent(WORD notifyCode)
[通知] 親ウィンドウへ通知.
void SetInsertMode(bool isEnable)
[設定] インサートモード設定.
void ShowCaretAlways(void)
[設定] 常にカレット表示.
void SetSel(int startIndex, int endIndex)
[設定] 選択位置設定.
void ReplaceSel(LPCTSTR lpszText)
[置換] データ置換.
シングルラインHEXデータ入力Editコントロール
TNB::CVectorT< BYTE > CByteVector
BYTE配列管理クラス
Definition: TnbVector.h:1122
LRESULT SendCommandMessage(CWnd *pCtrl, UINT cmd)
[処理] WM_COMMAND送信.
Definition: TnbMfcCommon.h:475
char IntToHexChar(int c)
[変換] 数値HEX文字変換
Definition: TnbStrLib.h:518
int HexCharToInt(int c)
[変換] HEX文字数値変換
Definition: TnbStrLib.h:492
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
void Swap(T &t1, T &t2)
[変換] スワッパー.
Definition: TnbDef.h:963
TNB Library
Definition: TnbDoxyTitle.txt:2