自繪16進位制編輯框
阿新 • • 發佈:2019-01-22
這個東西的產生是因為有朋友需要一個16進位制編輯器控制元件,但是網路上的大多數控制元件呼叫都不是那麼方便
找了很多也不好用,才萌生了自己魯一個16進位制編輯框 控制元件,先後路過兩個版本,第一個版本程式碼冗長,
框架設計不是這麼合理,所以才有了現在的這個版本,目前這個版本是沒有優化的版本,為了新手能看懂
大部分程式碼都沒有優化,全部都是自己魯,要用到自己的程式裡面還欠缺一點,大家需要自己去熟悉框架
只有熟悉了框架,才能更好的修改,優化過後,是完全能勝任的,優點嘛就是簡單,方便嵌入程式使用
缺點就是功能還沒有這麼多,不過大家可以關注,以後會有更多功能版本的出來,這裡帖一下程式碼,程式碼大約有
1800行不到
16進位制編輯器 控制元件開發SDK
整個工程打包在這裡下載
http://download.csdn.net/detail/u012607841/9690273
開啟2G的檔案和預覽拖動都是比較快的。
#define USE_GDIPACK #define USE_GDIPLUS #include "Common.h" #include "DrawPack.h" #include <map> class XFile { public: BOOL Open(const wchar_t* lpFileName) { m_hFile = CreateFileW( lpFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (m_hFile == INVALID_HANDLE_VALUE) return FALSE; return TRUE; } VOID Close() { CloseHandle(m_hFile); } BOOL SetPoint(int nPos) { return SetFilePointer(m_hFile,nPos,NULL,FILE_BEGIN) == INVALID_SET_FILE_POINTER ? FALSE:FALSE; } BOOL Read(VOID* pBuffer,DWORD dwBufferSize,DWORD* pdwRealReadSize) { return ReadFile(m_hFile,pBuffer,dwBufferSize,pdwRealReadSize,NULL); } BOOL WriteChar(char ch) { DWORD dwWriteByts = 0; return ::WriteFile(m_hFile,&ch,1,&dwWriteByts,NULL); } BOOL GetSizeMoreThan4GB(PLARGE_INTEGER fileSize) { return GetFileSizeEx(m_hFile,fileSize); } BOOL GetSizeLessThan4GB(DWORD* pdwSize) { LARGE_INTEGER fullSize; BOOL bOk = GetSizeMoreThan4GB(&fullSize); *pdwSize = fullSize.LowPart; return bOk; } private: HANDLE m_hFile; }; class XBuffer { public: XBuffer() { m_pBuffer = NULL; } ~XBuffer() { if (m_pBuffer) delete [] m_pBuffer; } void ReSize(int size) { if (size < m_MaxShowCount) { m_MaxShowCount = size; return ; } if (m_pBuffer) delete [] m_pBuffer; m_pBuffer = new char[size]; m_MaxShowCount = size; } public: char* m_pBuffer; int m_MaxShowCount; }; //修改的資料儲存類 class XModiyData { public: //ch 被修改的引數 //pos 被修改資料的絕對位置 void push(int pos,char ch) { std::map<int,char>::iterator it = m_data.find(pos); if ( it != m_data.end()) { it->second = ch; }else { m_data.insert(std::pair<int,char>(pos,ch)); } } BOOL pop(char* pCh,int * pPos) { if (IsEmpty()) return FALSE; std::map<int,char>::iterator it = m_data.end(); it--; if (pCh != NULL && pPos != NULL) { *pCh = it->second; *pPos = it->first; } m_data.erase(it); return TRUE; } BOOL IsEmpty() { return m_data.empty(); } VOID Clear() { m_data.clear(); } BOOL IsDataModify(int pos,char* pCh) { if (IsEmpty()) return FALSE; std::map<int,char>::iterator it = m_data.find(pos); if (it == m_data.end()) return FALSE; *pCh = it->second; return TRUE; } std::map<int,char>::iterator GetBegin() { return m_data.begin(); } std::map<int,char>::iterator GetEnd() { return m_data.end(); } private: std::map<int,char> m_data; }; class XHexFilter { public: XHexFilter() { memset(m_TableArray,'.',256); unsigned char ch = 33; for (; ch < 128; ch++) { m_TableArray[ch] = ch; } m_TableArray[127] = '.'; } void SetFilter(unsigned char index,char showedChar) { m_TableArray[index]= showedChar; } char* Filter(char* lpChar) { return m_TableArray + (unsigned char)*lpChar; } private: char m_TableArray[256]; }; class DataFormat { public: DataFormat() { ZeroMemory(pDicTable, 256); pDicTable['0'] = 0; pDicTable['1'] = 1; pDicTable['2'] = 2; pDicTable['3'] = 3; pDicTable['4'] = 4; pDicTable['5'] = 5; pDicTable['6'] = 6; pDicTable['7'] = 7; pDicTable['8'] = 8; pDicTable['9'] = 9; pDicTable['A'] = 10; pDicTable['B'] = 11; pDicTable['C'] = 12; pDicTable['D'] = 13; pDicTable['E'] = 14; pDicTable['F'] = 15; pDicTable['a'] = 10; pDicTable['b'] = 11; pDicTable['c'] = 12; pDicTable['d'] = 13; pDicTable['e'] = 14; pDicTable['f'] = 15; } wchar_t HexStrToChar(const wchar_t* pBuf) { wchar_t result = 0; result |= ((pDicTable[pBuf[0]] << 4) & 0xF0); result |= pDicTable[pBuf[1]]; return result; } // 比如a 的16進位制字串是 61 此時可以修改 6或者 1 char CharModiy(char chSrc,int nIndex,wchar_t md) { char result = '\0'; if (nIndex == 0) {//修改高位 result |= pDicTable[md]; result <<= 4; result |= (chSrc&0x0f); } else // == 1 修改低位 { result = chSrc&0xf0; result |= pDicTable[md]; } return result; } wchar_t* CharToHexStr(wchar_t ch) { wchar_t pHexToDecTable[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; buffer[0] = pHexToDecTable[(ch & 0xf000) >> 12]; buffer[1] = pHexToDecTable[(ch & 0xf00) >> 8]; buffer[2] = pHexToDecTable[(ch & 0xf0) >> 4]; buffer[3] = pHexToDecTable[(ch & 0xf)]; buffer[4] = 0; return buffer; } private: wchar_t pDicTable[256]; wchar_t buffer[5]; }; class XPartBase { public: VOID SetRect(int x,int y,int cx,int cy) { m_rt.left = x; m_rt.top = y; m_rt.right = x+cx; m_rt.bottom = y+cy; } VOID GetRect(RECT* pRect) { *pRect = m_rt; } protected: RECT m_rt; }; class XPart1 : public XPartBase { public: XPart1() { ZeroMemory(m_lpText,256); wcscat(m_lpText,L"offset"); } VOID SetText(const wchar_t* lpText) { wcscpy(m_lpText,lpText); } void Draw(XGDIMEMDC* pMemDC) { pMemDC->DrawText(m_lpText,wcslen(m_lpText),&m_rt,DT_CENTER|DT_VCENTER); } private: wchar_t m_lpText[128]; }; class XPart2 : public XPartBase { public: XPart2() { //m_lpText = L"000102030405060708090A0B0C0D0E0F"; m_lpText = L"0123456789ABCDEF"; } int GetChCount() { return 16; } VOID SetChRect(int nIndex,int x,int y,int cx,int cy) { m_rtArray[nIndex].left = x; m_rtArray[nIndex].top = y; m_rtArray[nIndex].right = x+cx; m_rtArray[nIndex].bottom = y+cy; } VOID Draw(XGDIMEMDC* pMemDC) { for (int i = 0; i < 16; i++) { pMemDC->DrawRect1(m_rtArray+i); pMemDC->DrawText(m_lpText+i,1,m_rtArray+i,DT_LEFT|DT_VCENTER); } } private: RECT m_rtArray[16]; wchar_t* m_lpText; }; class XPart3 : public XPartBase { public: XPart3() { m_lpText = L"0123456789ABCDEF"; } int GetChCount() { return 16; } VOID SetChRect(int nIndex,int x,int y,int cx,int cy) { m_rtArray[nIndex].left = x; m_rtArray[nIndex].top = y; m_rtArray[nIndex].right = x+cx; m_rtArray[nIndex].bottom = y+cy; } VOID Draw(XGDIMEMDC* pMemDC) { for (int i = 0; i < 16; i++) { pMemDC->DrawRect1(m_rtArray+i); pMemDC->DrawText(m_lpText+i,1,m_rtArray+i,DT_LEFT|DT_VCENTER); } } private: RECT m_rtArray[16]; wchar_t* m_lpText; }; class XPart4 : public XPartBase { public: XPart4() { m_buffer[8]=L'\0'; m_nScorbarPos = 0; } VOID SetChRect(int nIndex,int x,int y,int cx,int cy) { m_rtArray[nIndex].left = x; m_rtArray[nIndex].top = y; m_rtArray[nIndex].right = x+cx; m_rtArray[nIndex].bottom = y+cy; } int GetRowCount() { return m_nMaxShowRowCount; } VOID SetRowCount(int nRowCount) { m_nMaxShowRowCount = nRowCount; } VOID SetScrollPos(int nPos) { m_nScorbarPos = nPos; } VOID Draw(XGDIMEMDC* pMemDC) { for (int i = 0; i < m_nMaxShowRowCount; i++) { wsprintfW(m_buffer,L"%08X",i+m_nScorbarPos); pMemDC->TextOutW(m_rtArray[i].left,m_rtArray[i].top,m_buffer,8); } } private: wchar_t m_buffer[9]; RECT m_rtArray[1000]; int m_nMaxShowRowCount; int m_nScorbarPos; }; class XPart5 : public XPartBase { public: XPart5() { m_pRtArray = NULL; m_ArraySize = 0; } VOID ReSize(int nSize) { if (nSize < m_ArraySize) { m_ArraySize = nSize; return ; } if (m_ArraySize != NULL) { delete [] m_pRtArray; m_pRtArray = new RECT[nSize]; }else { m_pRtArray = new RECT[nSize]; } m_ArraySize = nSize; } int GetArrayCount() { return m_ArraySize; } void SetHexsRect(int nIndex,int x,int y,int cx,int cy) { m_pRtArray[nIndex].left = x; m_pRtArray[nIndex].top = y; m_pRtArray[nIndex].right = x+cx; m_pRtArray[nIndex].bottom = y+cy; } void GetHexsRect(int nIndex,RECT *pRect) { *pRect = m_pRtArray[nIndex]; } private: RECT* m_pRtArray; int m_ArraySize; }; class XPart6 : public XPart5 { public: XPart6() { } }; #define HEX_TEXT_HEIGHT 14 #define SPLIT1_WIDTH 10 #define SPLIT2_WIDTH 10 enum CARET_IN_ { CARET_IN_PART1 = 1, CARET_IN_PART2, CARET_IN_PART3, CARET_IN_PART4, CARET_IN_PART5, CARET_IN_PART6, }; class XHexEdit { public: XHexEdit() { m_PaddingLeft = 5; m_PaddingTop = 0; m_nPart2BlockWidth = 20; m_nPart2BlockSpace = 6; m_nPart3BlockWidth = 15; m_nRowHeight = HEX_TEXT_HEIGHT; m_nScorBarVPos = 0; m_nScorBarHPos = 0; ZeroMemory(&m_SelectStart,sizeof(m_SelectStart)); ZeroMemory(&m_SelectEnd,sizeof(m_SelectEnd)); } HELE Create(int x,int y,int cx,int cy,HXCGUI hParent) { m_x = x, m_y = y,m_cx = cx, m_cy = cy; m_hScrollView=XSView_Create(m_x,m_y,m_cx,m_cy,hParent); XEle_RegEventCPP(m_hScrollView,XE_SCROLLVIEW_SCROLL_H,&XHexEdit::OnScrollViewScrollH); XEle_RegEventCPP(m_hScrollView,XE_SCROLLVIEW_SCROLL_V,&XHexEdit::OnScrollViewScrollV); XEle_RegEventCPP(m_hScrollView,XE_SIZE,&XHexEdit::OnSize); XEle_RegEventCPP(m_hScrollView,XE_PAINT_SCROLLVIEW,&XHexEdit::OnDrawScrollView); XEle_RegEventCPP(m_hScrollView,XE_MOUSEMOVE,&XHexEdit::OnMouseMove); XEle_RegEventCPP(m_hScrollView,XE_LBUTTONDOWN,&XHexEdit::OnLButtonDown); XEle_RegEventCPP(m_hScrollView,XE_KEYDOWN,&XHexEdit::OnEventKeyDown); XEle_RegEventCPP(m_hScrollView,XE_CHAR,&XHexEdit::OnEventChar); XSView_SetBorderSize(m_hScrollView,0,0,0,0); m_Caret.Create(m_hScrollView,1,m_nRowHeight); m_Caret.SetColor(RGB(128,0,0)); m_MemDC.Create(XEle_GetHWND(m_hScrollView)); XEle_PostEvent(m_hScrollView,m_hScrollView,XE_SIZE,NULL,NULL); return m_hScrollView; } BOOL LoadFile(const wchar_t* lpFileName) { if (!m_File.Open(lpFileName)) return FALSE; //元素控制元件大小變化 重新計算檢視總大小 LARGE_INTEGER fileSize; m_File.GetSizeMoreThan4GB(&fileSize); DWORD nRowCount = fileSize.LowPart / 16 + ( fileSize.LowPart % 16?1:0) ; int nRowHeight = m_PaddingTop+m_nRowHeight+nRowCount*m_nRowHeight+100; XSView_SetTotalSize(m_hScrollView,800,nRowHeight); XSView_SetLineSize(m_hScrollView,m_nRowHeight,m_nRowHeight); XEle_PostEvent(m_hScrollView,m_hScrollView,XE_SIZE,NULL,NULL); m_nScorBarVPos = 0; return TRUE; } BOOL SaveModiy() { std::map<int,char>::iterator it = m_ModData.GetBegin(); while (it != m_ModData.GetEnd()) { int nIndex = it->first; char ch = it->second; m_File.SetPoint(nIndex); m_File.WriteChar(ch); it++; } m_ModData.Clear(); return TRUE; } //事件介面 public: int OnEventChar(WPARAM wParam,LPARAM lParam,BOOL *pbHandled) { //過濾 if (wParam == 8) return 0; //此時游標的位置得判斷是在part5 還是在part6 SELECT CaretInfo = m_SelectEnd; if (CaretInfo.m_CaretInWichPart == CARET_IN_PART5) { BOOL bFilter = TRUE; if ( wParam >= '0' && wParam <= '9') { bFilter = FALSE; } else if ( wParam >= 'a' && wParam <= 'f') { bFilter = FALSE; } else if( wParam >= 'A' && wParam <= 'F') { bFilter = FALSE; } SELECT CaretInfo = m_SelectEnd; //如果需要過濾就直接過濾了 if ( bFilter == TRUE) return 0; //否則處理訊息 //首先判斷是否已經修改過了。。。。 char oldChar='0'; int nScorllHideSize = m_nScorBarVPos*16; int nBufferIndex = CaretInfo.m_DataIndex - nScorllHideSize; if (m_ModData.IsDataModify(CaretInfo.m_DataIndex,&oldChar)) { //如果修改過,則用修改過的資料 char newCh = m_Format.CharModiy(oldChar,CaretInfo.m_TextIndex,(wchar_t)wParam); m_ModData.push(nBufferIndex+nScorllHideSize,newCh); } else { char newCh = m_Format.CharModiy(m_Buffer.m_pBuffer[nBufferIndex],CaretInfo.m_TextIndex,(wchar_t)wParam); m_ModData.push(nBufferIndex+nScorllHideSize,newCh); } XEle_PostEvent(m_hScrollView,m_hScrollView,XE_KEYDOWN,VK_RIGHT,NULL); XEle_RedrawEle(m_hScrollView); return 0; } if (CaretInfo.m_CaretInWichPart == CARET_IN_PART6) { int nBufferIndex = CaretInfo.m_DataIndex; //後面還要修復 m_ModData.push(nBufferIndex,(char)wParam); XEle_PostEvent(m_hScrollView,m_hScrollView,XE_KEYDOWN,VK_RIGHT,NULL); XEle_RedrawEle(m_hScrollView); return 0; } return 0; } int OnEventKeyDown(WPARAM wParam,LPARAM lParam,BOOL *pbHandled) { #ifdef _DEBUG xtrace("keydown %d \r\n",wParam); #endif if (wParam == VK_RIGHT) { SELECT CaretInfo = m_SelectEnd; //分兩種情況 //在part5 還是在part6 if (CaretInfo.m_CaretInWichPart == CARET_IN_PART5) { DWORD dwFileSize = 0; m_File.GetSizeLessThan4GB(&dwFileSize); if (CaretInfo.m_DataIndex == dwFileSize && CaretInfo.m_TextIndex == 1) return 0; //在末尾 RECT rt; if (CaretInfo.m_TextIndex == 0) { int nBufferIndex =CaretInfo.m_DataIndex - m_nScorBarVPos*16; m_Part5.GetHexsRect(nBufferIndex,&rt); CaretInfo.m_TextIndex = 1; wchar_t* pHexText = m_Format.CharToHexStr(m_Buffer.m_pBuffer[nBufferIndex]); rt.left += m_MemDC.GetTextWidth(pHexText+2,1); }else { CaretInfo.m_DataIndex++; CaretInfo.m_TextIndex = 0; int nBufferIndex =CaretInfo.m_DataIndex - m_nScorBarVPos*16; m_Part5.GetHexsRect(nBufferIndex,&rt); } //相對座標轉化成絕對的座標 rt.top += m_nScorBarVPos*m_nRowHeight; m_Caret.SetPos(rt.left,rt.top); m_Caret.Show(TRUE); //還要分是否按住了 ctrl鍵 if(GetAsyncKeyState(VK_SHIFT)&0x8000) { //多選 m_SelectEnd = CaretInfo; XEle_RedrawEle(m_hScrollView); }else { //設定當前游標位置 m_SelectEnd = CaretInfo; m_SelectStart = CaretInfo; } } if (CaretInfo.m_CaretInWichPart == CARET_IN_PART6) { DWORD dwFileSize = 0; m_File.GetSizeLessThan4GB(&dwFileSize); if (CaretInfo.m_DataIndex == dwFileSize) return 0; //在末尾 CaretInfo.m_DataIndex++; int nBufferIndex =CaretInfo.m_DataIndex - m_nScorBarVPos*16; RECT rt; m_Part6.GetHexsRect(nBufferIndex,&rt); //相對座標轉化成絕對的座標 rt.top += m_nScorBarVPos*m_nRowHeight; m_Caret.SetPos(rt.left,rt.top); m_Caret.Show(TRUE); //還要分是否按住了 ctrl鍵 if(GetAsyncKeyState(VK_SHIFT)&0x8000) { //多選 m_SelectEnd = CaretInfo; XEle_RedrawEle(m_hScrollView); }else { //設定當前游標位置 m_SelectEnd = CaretInfo; m_SelectStart = CaretInfo; } } return 0; } if (wParam == VK_LEFT) { SELECT CaretInfo = m_SelectEnd; if (CaretInfo.m_DataIndex == 0) return 0; //到最開頭了 //否則 CaretInfo.m_DataIndex--; CaretInfo.m_TextIndex=0; int nBufferIndex =CaretInfo.m_DataIndex - m_nScorBarVPos*16; RECT rt; if (CaretInfo.m_CaretInWichPart == CARET_IN_PART5) { m_Part5.GetHexsRect(nBufferIndex,&rt); }else if(CaretInfo.m_CaretInWichPart == CARET_IN_PART6) { m_Part6.GetHexsRect(nBufferIndex,&rt); }else { return 0; } //相對座標轉化成絕對的座標 rt.top += m_nScorBarVPos*m_nRowHeight; m_Caret.SetPos(rt.left,rt.top); m_Caret.Show(TRUE); //還要分是否按住了 ctrl鍵 if(GetAsyncKeyState(VK_SHIFT)&0x8000) { //多選 m_SelectEnd = CaretInfo; XEle_RedrawEle(m_hScrollView); }else { //設定當前游標位置 m_SelectEnd = CaretInfo; m_SelectStart = CaretInfo; } } // 90 == z if (wParam == 90 && GetAsyncKeyState(VK_CONTROL)&0x8000) { //撤銷修改 m_ModData.pop(NULL,NULL); XEle_RedrawEle(m_hScrollView); return 0; } // 83 == s if (wParam == 83 && GetAsyncKeyState(VK_CONTROL)&0x8000) { //儲存修改 SaveModiy(); // XSView_ScrollPosV(m_hScrollView,m_nScorBarVPos); XEle_SendEvent(m_hScrollView,m_hScrollView,XE_SCROLLVIEW_SCROLL_V,(WPARAM)m_nScorBarVPos,NULL); *pbHandled = TRUE; return 0; } return 0; } int OnLButtonDown(UINT nFlags, POINT *pPt,BOOL *pbHandled) { SIZE LineSize; XSView_GetLineSize(m_hScrollView,&LineSize); pPt->x += LineSize.cx*m_nScorBarHPos; //點選位置是相對位置要轉換成絕對位置 RECT rt; m_Part5.GetRect(&rt); if (IsPtInRect2(pPt,&rt)) { int nColIndex = (pPt->x - m_PaddingLeft - m_Part1Width)/(m_nPart2BlockWidth+m_nPart2BlockSpace); int nRowIndex = (pPt->y - m_PaddingTop - m_nRowHeight)/m_nRowHeight; //如果當前點選座標所在索引大於可顯示數量則忽略 if (nRowIndex *16 + nColIndex >= m_nRealShowSize) return 0; int nOffsetIndex = nRowIndex *16 + nColIndex + m_nScorBarVPos*16; wchar_t txtBuffer[9] = {0}; wsprintfW(txtBuffer,L"%08X",nOffsetIndex); m_part1.SetText(txtBuffer); m_SelectStart.m_CaretInWichPart = CARET_IN_PART5; m_SelectStart.m_DataIndex = nOffsetIndex; RECT rtCh; m_Part5.GetHexsRect(nRowIndex *16 + nColIndex,&rtCh); char ch = m_Buffer.m_pBuffer[nRowIndex *16 + nColIndex]; wchar_t* pHexChar = m_Format.CharToHexStr((wchar_t)ch); int chWidth = m_MemDC.GetTextWidth(pHexChar+2,1); int nCaretPosX = rtCh.left; int nCaretPosY = rtCh.top; if (pPt->x > rtCh.left+chWidth) { nCaretPosX = rtCh.left+chWidth; m_SelectStart.m_TextIndex = 1; }else { nCaretPosX = rtCh.left; m_SelectStart.m_TextIndex = 0; } //儲存游標位置 m_SelectEnd = m_SelectStart; //相對座標轉化成絕對的座標 nCaretPosY += m_nScorBarVPos*LineSize.cy; //最後顯示游標 m_Caret.SetPos(nCaretPosX,nCaretPosY); m_Caret.Show(TRUE); xtrace("caret in part5 Col=%d row=%d \r\n",nColIndex,nRowIndex); XEle_RedrawEle(m_hScrollView); return 0; } m_Part6.GetRect(&rt); if (IsPtInRect2(pPt,&rt)) { int nColIndex = (pPt->x - m_PaddingLeft - m_Part1Width - SPLIT1_WIDTH - m_Part2Width - SPLIT2_WIDTH )/(m_nPart3BlockWidth); int nRowIndex = (pPt->y - m_nRowHeight)/m_nRowHeight; //如果當前點選座標所在索引大於可顯示數量則忽略 if (nRowIndex *16 + nColIndex >= m_nRealShowSize) return 0; int nOffsetIndex = nRowIndex *16 + nColIndex + m_nScorBarVPos*16; wchar_t txtBuffer[9] = {0}; wsprintfW(txtBuffer,L"%08X",nOffsetIndex); m_part1.SetText(txtBuffer); m_SelectStart.m_CaretInWichPart = CARET_IN_PART6; m_SelectStart.m_DataIndex = nOffsetIndex; m_SelectStart.m_TextIndex = 0; m_SelectEnd = m_SelectStart; RECT rtCh; m_Part6.GetHexsRect(nRowIndex *16 + nColIndex,&rtCh); int nCaretPosX = rtCh.left; int nCaretPosY = rtCh.top; //相對座標轉化成絕對的座標 nCaretPosY += m_nScorBarVPos*m_nRowHeight; //最後顯示游標 m_Caret.SetPos(nCaretPosX,nCaretPosY); m_Caret.Show(TRUE); xtrace("caret in part6 Col=%d row=%d \r\n",nColIndex,nRowIndex); XEle_RedrawEle(m_hScrollView); return 0; } return 0; } int OnMouseMove(UINT nFlags, POINT *pPt, BOOL *pbHandled) { SIZE LineSize; XSView_GetLineSize(m_hScrollView,&LineSize); pPt->x += LineSize.cx*m_nScorBarHPos; m_MousePosX = pPt->x ; m_MousePosy = pPt->y; if ( (nFlags & MK_LBUTTON) == 0) { XEle_RedrawEle(m_hScrollView,FALSE); return 0; } RECT rt; m_Part5.GetRect(&rt); if (IsPtInRect2(pPt,&rt)) { if (CARET_IN_PART6 == m_SelectStart.m_CaretInWichPart) { //滑鼠按下的時候是 在 part6 但是當前為part5,直接忽略 XEle_RedrawEle(m_hScrollView); return 0; } int nColIndex = (pPt->x - m_PaddingLeft - m_Part1Width)/(m_nPart2BlockWidth+m_nPart2BlockSpace); int nRowIndex = (pPt->y - m_PaddingTop - m_nRowHeight)/m_nRowHeight; //如果當前點選座標所在索引大於可顯示數量則忽略 if (nRowIndex *16 + nColIndex >= m_nRealShowSize) return 0; int nOffsetIndex = nRowIndex *16 + nColIndex + m_nScorBarVPos*16; wchar_t txtBuffer[9] = {0}; wsprintfW(txtBuffer,L"%08X",nOffsetIndex); m_part1.SetText(txtBuffer); m_SelectEnd.m_CaretInWichPart = CARET_IN_PART5; m_SelectEnd.m_DataIndex = nOffsetIndex; RECT rtCh; m_Part5.GetHexsRect(nRowIndex *16 + nColIndex,&rtCh); char ch = m_Buffer.m_pBuffer[nRowIndex *16 + nColIndex]; wchar_t* pHexChar = m_Format.CharToHexStr((wchar_t)ch); int chWidth = m_MemDC.GetTextWidth(pHexChar+2,1); int nCaretPosX = rtCh.left; int nCaretPosY = rtCh.top; if (pPt->x > rtCh.left+chWidth) { nCaretPosX = rtCh.left+chWidth; m_SelectEnd.m_TextIndex = 1; }else { nCaretPosX = rtCh.left; m_SelectEnd.m_TextIndex = 0; } //相對座標轉化成絕對的座標 nCaretPosY += m_nScorBarVPos*m_nRowHeight; //最後顯示游標 m_Caret.SetPos(nCaretPosX,nCaretPosY); m_Caret.Show(TRUE); xtrace("caret in part5 Col=%d row=%d \r\n",nColIndex,nRowIndex); XEle_RedrawEle(m_hScrollView); return 0; } m_Part6.GetRect(&rt); if (IsPtInRect2(pPt,&rt)) { if (m_SelectStart.m_CaretInWichPart == CARET_IN_PART5) { //滑鼠按下的時候是 在 part5 但是當前為part,直接忽略 XEle_RedrawEle(m_hScrollView); return 0; } int nColIndex = (pPt->x - m_PaddingLeft - m_Part1Width - SPLIT1_WIDTH - m_Part2Width - SPLIT2_WIDTH )/(m_nPart3BlockWidth); int nRowIndex = (pPt->y - m_nRowHeight)/m_nRowHeight; //如果當前點選座標所在索引大於可顯示數量則忽略 if (nRowIndex *16 + nColIndex >= m_nRealShowSize) return 0; int nOffsetIndex = nRowIndex *16 + nColIndex + m_nScorBarVPos*16; wchar_t txtBuffer[9] = {0}; wsprintfW(txtBuffer,L"%08X",nOffsetIndex); m_part1.SetText(txtBuffer); m_SelectEnd.m_CaretInWichPart = CARET_IN_PART6; m_SelectEnd.m_DataIndex = nOffsetIndex; m_SelectEnd.m_TextIndex = 0; RECT rtCh; m_Part6.GetHexsRect(nRowIndex *16 + nColIndex,&rtCh); int nCaretPosX = rtCh.left; int nCaretPosY = rtCh.top; //相對座標轉化成絕對的座標 nCaretPosY += m_nScorBarVPos*m_nRowHeight; //最後顯示游標 m_Caret.SetPos(nCaretPosX,nCaretPosY); m_Caret.Show(TRUE); xtrace("caret in part6 Col=%d row=%d \r\n",nColIndex,nRowIndex); XEle_RedrawEle(m_hScrollView); return 0; } XEle_RedrawEle(m_hScrollView,FALSE); return 0; } int OnSize(BOOL *pbHandled) { //當視窗元素大小變化後,導致滾動條範圍大小變化, //此時滾動條所在位置 //控制元件大小變化,需要做幾件事 //1 重新計算緩衝區大小 //2 重新讀取指定位置資料 //3 重新計算各個part的座標 //4 重新定位插入符Caret座標 m_cx = XEle_GetWidth(m_hScrollView); m_cy = XEle_GetHeight(m_hScrollView); m_MemDC.Resize(1000,m_cy); //計算當前元素最大能顯示多少個字元 int cy = m_cy - m_PaddingTop - m_nRowHeight; int nShowBufferSize = (cy / m_nRowHeight + ((cy % m_nRowHeight)?1:0))*16; m_Buffer.ReSize(nShowBufferSize); XEle_SendEvent(m_hScrollView,m_hScrollView,XE_SCROLLVIEW_SCROLL_V,(WPARAM)m_nScorBarVPos,NULL); #ifdef _DEBUG xtrace("ViewPosH %d %d --\r\n",XSView_GetViewPosH(m_hScrollView),XSView_GetViewPosV(m_hScrollView)); #endif // m_File.SetPoint(m_nScorBarVPos*16); // // m_File.Read(m_Buffer.m_pBuffer,m_Buffer.m_MaxShowCount,&m_nRealShowSize); // // #ifdef _DEBUG // xtrace("調整大小前後實際顯示數量 %d %d\r\n",nShowBufferSize,m_nRealShowSize); // #endif // // m_nRealRowCount = m_nRealShowSize / 16 + (m_nRealShowSize%16?1:0); // m_Part4.SetRowCount(m_nRealRowCount); // // // m_Part5.ReSize(m_nRealShowSize); // m_Part6.ReSize(m_nRealShowSize); // // AutoCalcPartsRect(); return 0; } int OnScrollViewScrollH(int pos,BOOL *pbHandled) { m_nScorBarHPos = pos; XTRACE("XE_SCROLLVIEW_SCROLL_H %d \n",pos); return 0; } int OnScrollViewScrollV(int pos,BOOL *pbHandled) { //滾動條滾動 需要做的幾件事 // 第一,讀取滾動條位置的資料, // 第二,如果實際讀取的資料小於可顯示的資料,那麼重新儲存一下 // 第三 重新計算各個part的座標 m_nScorBarVPos = pos; m_File.SetPoint(m_nScorBarVPos*16); m_File.Read(m_Buffer.m_pBuffer,m_Buffer.m_MaxShowCount,&m_nRealShowSize); m_nRealRowCount = m_nRealShowSize / 16 + (m_nRealShowSize%16?1:0); m_Part4.SetRowCount(m_nRealRowCount); m_Part4.SetScrollPos(m_nScorBarVPos); m_Part5.ReSize(m_nRealShowSize); m_Part6.ReSize(m_nRealShowSize); AutoCalcPartsRect(); XTRACE("XE_SCROLLVIEW_SCROLL_V %d \n",pos); return 0; } //分為6個部分 // | part1 | part2 | part3| // |----------------------| // | part4 | part5 | part6| // | | | | // part1 == offset 字串 // part2 == 0 - F 列標示 // part3 == 0 - F 字元顯示 // part4 == 00000000 - FFFFFFFF 行號 // part5 == 十六進位制顯示 // part6 == 字元形式顯示 int OnDrawScrollView(HDRAW hDraw,BOOL *pbHandled) { m_MemDC.FillRect(0,0,m_MemDC.GetBitMapWidth(),m_MemDC.GetBitMapHeight()); m_MemDC.SetTextColor(RGB(128,18,0)); // draw offset m_part1.Draw(&m_MemDC); m_MemDC.SetTextColor(RGB(0,0,128)); m_part2.Draw(&m_MemDC); m_Part3.Draw(&m_MemDC); m_MemDC.SetTextColor(0); m_Part4.Draw(&m_MemDC); #ifdef _DEBUG xtrace("type=%d Index=%d tpye=%d Index =%d\r\n",m_SelectStart.m_CaretInWichPart,m_SelectStart.m_DataIndex, m_SelectEnd.m_CaretInWichPart,m_SelectEnd.m_DataIndex); #endif //這裡需要判斷是否有選中 if (m_SelectStart.m_DataIndex == m_SelectEnd.m_DataIndex) { //沒有選中 wchar_t buffer[10] = {0}; RECT rt; int nScrollPos = m_nScorBarVPos*16; char Modifych; for (int k = 0 ; k < m_Part5.GetArrayCount(); k++) { m_Part5.GetHexsRect(k,&rt); if (m_ModData.IsDataModify(k+nScrollPos,&Modifych)) { //是修改過的資料 wchar_t* pStrHex= m_Format.CharToHexStr(Modifych); COLORREF oldCor = m_MemDC.SetTextColor(RGB(255,0,0)); m_MemDC.TextOutW(rt.left,rt.top,pStrHex+2,2); m_MemDC.SetTextColor(oldCor); }else { //資料沒有修改過 wchar_t* pStrHex = m_Format.CharToHexStr((wchar_t)(m_Buffer.m_pBuffer[k])); m_MemDC.TextOutW(rt.left,rt.top,pStrHex+2,2); } } RECT rt6; for (int m = 0 ; m < m_Part6.GetArrayCount();m++) { m_Part6.GetHexsRect(m,&rt6); if (m_ModData.IsDataModify(m+nScrollPos,&Modifych)) { //是修改過的資料 COLORREF oldCor = m_MemDC.SetTextColor(RGB(255,0,0)); m_MemDC.TextOutA(rt6.left,rt6.top,m_HexFilter.Filter(&Modifych),1); m_MemDC.SetTextColor(oldCor); }else { //資料沒有修改過 m_MemDC.TextOutA(rt6.left,rt6.top,m_HexFilter.Filter(m_Buffer.m_pBuffer+m),1); } } }else{ //有選中 int nSelectStart = 0; int nSelectEnd = 0; if (m_SelectStart.m_DataIndex > m_SelectEnd.m_DataIndex) { nSelectStart = m_SelectEnd.m_DataIndex; nSelectEnd = m_SelectStart.m_DataIndex; } else { nSelectStart = m_SelectStart.m_DataIndex; nSelectEnd = m_SelectEnd.m_DataIndex; } #ifdef _DEBUG xtrace("select start = %d select end = %d \r\n",nSelectStart,nSelectEnd); #endif wchar_t buffer[10] = {0}; RECT rt; int tmpIndex = 0; //把字元的相對索引轉換成絕對索引 才能判斷 COLORREF corBk; COLORREF corText; int nScorPos = m_nScorBarVPos*16; for (int k = 0 ; k < m_Part5.GetArrayCount(); k++) { tmpIndex = k + nScorPos; if ( (tmpIndex >= nSelectStart) && (tmpIndex <= nSelectEnd) ) { corBk = m_MemDC.SetBkColor(RGB(0,0,128)); corText = m_MemDC.SetTextColor(RGB(255,255,255)); }else { corBk = m_MemDC.SetBkColor(RGB(255,255,255)); corText = m_MemDC.SetTextColor(RGB(0,0,0)); } m_Part5.GetHexsRect(k,&rt); wchar_t* pStrHex = m_Format.CharToHexStr((wchar_t)(m_Buffer.m_pBuffer[k])); m_MemDC.TextOutW(rt.left,rt.top,pStrHex+2,2); m_MemDC.SetBkColor(corBk); m_MemDC.SetTextColor(corText); } RECT rt6; for (int m = 0 ; m < m_Part6.GetArrayCount();m++) { tmpIndex = m + nScorPos; if ( (tmpIndex >= nSelectStart) && (tmpIndex <= nSelectEnd) ) { corBk = m_MemDC.SetBkColor(RGB(0,0,128)); corText = m_MemDC.SetTextColor(RGB(255,255,255)); }else { corBk = m_MemDC.SetBkColor(RGB(255,255,255)); corText = m_MemDC.SetTextColor(RGB(0,0,0)); } m_Part6.GetHexsRect(m,&rt6); m_MemDC.TextOutA(rt6.left,rt6.top,m_HexFilter.Filter(m_Buffer.m_pBuffer+m),1); m_MemDC.SetBkColor(corBk); m_MemDC.SetTextColor(corText); } } HGDIOBJ hOldObj = m_MemDC.SelectObject(m_MemDC.GetStockObject(DC_PEN)); m_MemDC.SetDCPenColor(RGB(255,0,0)); //畫兩條線,滑鼠飄過即可識別 int x1,y1,x2,y2; x1 = 0; y1 = m_MousePosy; x2 = m_Part1Width; y2 = m_MousePosy; m_MemDC.DrawLine(x1,y1,x2,y2); int x3,y3,x4,y4; x3 = m_MousePosX; y3 = m_nRowHeight; x4 = m_MousePosX; y4 = 0; m_MemDC.DrawLine(x3,y3,x4,y4); m_MemDC.SelectObject(hOldObj); int x,y; XDraw_GetOffset(hDraw,&x,&y); m_MemDC.BitBlt3_(hDraw,0,y); XDraw_SetLineWidth(hDraw,m_nRowHeight); //畫兩條線,滑鼠飄過即可識別 // RECT rt1; // rt1.left = 0; // rt1.top = m_MousePosy; // rt1.right = m_Part1Width; // rt1.bottom = m_MousePosy+m_nRowHeight/2; // XDraw_FillRectColor(hDraw,&rt1,RGB(0,128,0),50); // // // RECT rt2; // rt2.left = m_MousePosX; // rt2.top = 0; // rt2.right = m_MousePosX+m_nPart2BlockWidth/2; // rt2.bottom = m_nRowHeight; // XDraw_FillRectColor(hDraw,&rt2,RGB(0,128,0),50); return 0; } private: VOID ReadFileData(int nPos) { DWORD dwRealReadSize = 0; m_File.SetPoint(nPos*16); m_File.Read(m_Buffer.m_pBuffer,m_Buffer.m_MaxShowCount,&dwRealReadSize); m_nRealShowSize = dwRealReadSize; } //自動計算所有part的座標 VOID AutoCalcPartsRect() { m_Part1Width = m_MemDC.GetTextWidth(L"00000000",8); int offsetX = m_PaddingLeft; int offsetY = m_PaddingTop; int x = offsetX; int y = offsetY; m_part1.SetRect(x,y,m_Part1Width,m_nRowHeight); x+= m_Part1Width; x+= SPLIT1_WIDTH; m_Part2Width = (m_nPart2BlockWidth+m_nPart2BlockSpace)*m_part2.GetChCount(); m_part2.SetRect(x,y,m_Part2Width,m_nRowHeight); int i ; for (i = 0; i < m_part2.GetChCount(); i++) { m_part2.SetChRect(i,x,y,m_nPart2BlockWidth,m_nRowHeight); x+=m_nPart2BlockWidth; x+=m_nPart2BlockSpace; } x+= SPLIT2_WIDTH; m_Part3Width = m_nPart3BlockWidth*m_Part3.GetChCount(); m_Part3.SetRect(x,y,m_Part3Width,m_nRowHeight); for (i = 0; i < m_Part3.GetChCount(); i++) { m_Part3.SetChRect(i,x,y,m_nPart3BlockWidth,m_nRowHeight); x+=m_nPart3BlockWidth; } x = offsetX; y += m_nRowHeight; for (i = 0; i < m_Part4.GetRowCount(); i++) { m_Part4.SetChRect(i,x,y,m_Part1Width,m_nRowHeight); y+=m_nRowHeight; } x = offsetX+SPLIT1_WIDTH+m_Part1Width; y = offsetY+m_nRowHeight; m_Part5.SetRect(x,y,m_Part2Width,m_cy-m_nRowHeight-offsetY); for (i = 0; i < m_Part5.GetArrayCount(); i++) { if ( (i % 16) == 0 && i != 0) { x = offsetX+SPLIT1_WIDTH+m_Part1Width; y+= m_nRowHeight; } m_Part5.SetHexsRect(i,x,y,m_nPart2BlockWidth,m_nRowHeight); x+=m_nPart2BlockWidth; x+=m_nPart2BlockSpace; } x = offsetX +m_Part1Width+SPLIT1_WIDTH+m_Part2Width+SPLIT2_WIDTH; y = offsetY + m_nRowHeight; m_Part6.SetRect(x,y,m_Part3Width,m_cy-m_nRowHeight); for (i = 0; i < m_Part6.GetArrayCount(); i++) { if ( (i %16) == 0 && i != 0) { x= offsetX +m_Part1Width+SPLIT1_WIDTH+m_Part2Width+SPLIT2_WIDTH; y+= m_nRowHeight; } m_Part6.SetHexsRect(i,x,y,m_nPart3BlockWidth,m_nRowHeight); x+=m_nPart3BlockWidth; } } private: int m_x; int m_y; int m_cx; int m_cy; HELE m_hScrollView; XFile m_File; XBuffer m_Buffer; DataFormat m_Format; XGDIMEMDC m_MemDC; int m_PaddingLeft; int m_PaddingTop; //行數索引文字的寬度 int m_Part1Width; int m_Part2Width; int m_Part3Width; int m_nPart2BlockWidth; //中間16進位制文字 單個寬度 int m_nPart2BlockSpace; //中間16進位制文字 間距 int m_nPart3BlockWidth; //中間16進位制文字 單個寬度 int m_nRowHeight; int m_nScorBarVPos; int m_nScorBarHPos; //水平滾動位置 //為什麼會有這個,因為讀取的實際資料可能大於編輯框可顯示的資料大小 DWORD m_nRealShowSize; int m_nRealRowCount; int m_MousePosX; int m_MousePosy; XPart1 m_part1; XPart2 m_part2; XPart3 m_Part3; XPart4 m_Part4; XPart5 m_Part5; XPart6 m_Part6; XHexFilter m_HexFilter; typedef struct _tagSelect { CARET_IN_ m_CaretInWichPart; int m_TextIndex; // 比如 FF 游標是 0,1 |FF 還是 F|F 如果是 part6 只有 0 int m_DataIndex; //絕對座標 buffer 偏移 + 滾動條pos }SELECT,*PSELECT; XCaret m_Caret; SELECT m_SelectStart; SELECT m_SelectEnd; XModiyData m_ModData; }; class CMyWindowScrollView { public: HWINDOW m_hWindow; XHexEdit m_HexEdit; CMyWindowScrollView() { Init(); } void Init() { m_hWindow = XWnd_Create(0, 0, 600, 300, L"炫彩介面庫視窗", NULL, xc_window_style_default); XBtn_SetType(XBtn_Create(5, 3, 60, 20, L"Close", m_hWindow),button_type_close); HELE hEle = m_HexEdit.Create(20,50,200,200,m_hWindow); m_HexEdit.LoadFile(L"g:\\1.bak"); HXCGUI hLayoutBody = XLayout_Create(); XWnd_BindLayoutObject(m_hWindow,window_position_body,hLayoutBody); XLayout_SetLayoutHeight(hLayoutBody,layout_size_type_fill,1); XLayout_SetLayoutWidth(hLayoutBody,layout_size_type_fill,1); XLayout_AddEle(hLayoutBody,hEle); XEle_SetLayoutWidth(hEle,layout_size_type_fill,1); XEle_SetLayoutHeight(hEle,layout_size_type_fill,1); XWnd_AdjustLayout(m_hWindow); XWnd_ShowWindow(m_hWindow,SW_SHOW); } }; int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { XInitXCGUI(); CMyWindowScrollView MyWindow; XRunXCGUI(); XExitXCGUI(); return TRUE; }
程式碼略多