2006-06-15 04:19:30 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "MemoryView.h"
|
2007-02-20 21:16:34 +00:00
|
|
|
#include "string_cast.h"
|
2007-02-28 20:20:18 +00:00
|
|
|
#include "win32/GdiObj.h"
|
|
|
|
#include "win32/ClientDeviceContext.h"
|
|
|
|
#include "lexical_cast_ex.h"
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
#define CLSNAME _T("CMemoryView")
|
2006-06-15 04:19:30 +00:00
|
|
|
#define XMARGIN 5
|
|
|
|
#define YMARGIN 5
|
|
|
|
#define YSPACE 0
|
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
using namespace std;
|
2007-02-28 20:20:18 +00:00
|
|
|
using namespace Framework;
|
2007-02-20 21:16:34 +00:00
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
CMemoryView::CMemoryView(HWND hParent, RECT* pR)
|
|
|
|
{
|
2007-02-28 20:20:18 +00:00
|
|
|
if(!DoesWindowClassExist(CLSNAME))
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
WNDCLASSEX w;
|
|
|
|
memset(&w, 0, sizeof(WNDCLASSEX));
|
|
|
|
w.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
w.lpfnWndProc = CWindow::WndProc;
|
|
|
|
w.lpszClassName = CLSNAME;
|
2007-02-21 20:53:33 +00:00
|
|
|
w.hbrBackground = NULL;
|
2006-06-15 04:19:30 +00:00
|
|
|
w.hInstance = GetModuleHandle(NULL);
|
|
|
|
w.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
RegisterClassEx(&w);
|
|
|
|
}
|
|
|
|
|
2007-02-20 21:16:34 +00:00
|
|
|
Create(WS_EX_CLIENTEDGE, CLSNAME, _T(""), WS_VISIBLE | WS_VSCROLL | WS_CHILD, pR, hParent, NULL);
|
2006-06-15 04:19:30 +00:00
|
|
|
SetClassPtr();
|
|
|
|
|
|
|
|
m_nSize = 0;
|
2007-02-28 20:20:18 +00:00
|
|
|
m_nSelectionStart = 0;
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
UpdateScrollRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
CMemoryView::~CMemoryView()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
HFONT CMemoryView::GetFont()
|
|
|
|
{
|
|
|
|
return (HFONT)GetStockObject(ANSI_FIXED_FONT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryView::ScrollToAddress(uint32 nAddress)
|
|
|
|
{
|
|
|
|
unsigned int nRow;
|
|
|
|
unsigned int nRows, nCols;
|
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
GetVisibleRowsCols(&nRows, &nCols);
|
|
|
|
|
|
|
|
//Humm, nvm...
|
|
|
|
if(nCols == 0) return;
|
|
|
|
if(nAddress >= m_nSize) return;
|
|
|
|
|
|
|
|
nRow = (nAddress / nCols);
|
|
|
|
|
|
|
|
memset(&si, 0, sizeof(SCROLLINFO));
|
|
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
|
|
si.nPos = nRow;
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
SetScrollInfo(m_hWnd, SB_VERT, &si, TRUE);
|
|
|
|
|
|
|
|
Redraw();
|
|
|
|
}
|
|
|
|
|
2007-02-28 20:51:06 +00:00
|
|
|
uint32 CMemoryView::GetSelection()
|
|
|
|
{
|
|
|
|
return m_nSelectionStart;
|
|
|
|
}
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
void CMemoryView::UpdateScrollRange()
|
|
|
|
{
|
|
|
|
unsigned int nTotalRows;
|
|
|
|
unsigned int nCols, nRows;
|
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
GetVisibleRowsCols(&nRows, &nCols);
|
|
|
|
|
|
|
|
if(nCols != 0)
|
|
|
|
{
|
|
|
|
nTotalRows = (m_nSize / nCols);
|
|
|
|
if((m_nSize % nCols) != 0) nTotalRows++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nTotalRows = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&si, 0, sizeof(SCROLLINFO));
|
|
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
|
|
si.nMin = 0;
|
|
|
|
if(nTotalRows <= nRows)
|
|
|
|
{
|
|
|
|
si.nMax = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
si.nMax = nTotalRows - nRows;
|
|
|
|
}
|
|
|
|
si.fMask = SIF_RANGE | SIF_DISABLENOSCROLL;
|
|
|
|
SetScrollInfo(m_hWnd, SB_VERT, &si, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CMemoryView::GetScrollOffset()
|
|
|
|
{
|
|
|
|
SCROLLINFO si;
|
|
|
|
memset(&si, 0, sizeof(SCROLLINFO));
|
|
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
GetScrollInfo(m_hWnd, SB_VERT, &si);
|
|
|
|
return si.nPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CMemoryView::GetScrollThumbPosition()
|
|
|
|
{
|
|
|
|
SCROLLINFO si;
|
|
|
|
memset(&si, 0, sizeof(SCROLLINFO));
|
|
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
|
|
si.fMask = SIF_TRACKPOS;
|
|
|
|
GetScrollInfo(m_hWnd, SB_VERT, &si);
|
|
|
|
return si.nTrackPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryView::GetVisibleRowsCols(unsigned int* pRows, unsigned int* pCols)
|
|
|
|
{
|
|
|
|
SIZE s;
|
|
|
|
RECT rc;
|
|
|
|
unsigned int nRows, nCols;
|
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
{
|
|
|
|
Win32::CClientDeviceContext DeviceContext(m_hWnd);
|
|
|
|
Win32::CFont Font(GetFont());
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
s = DeviceContext.GetFontSize(Font);
|
|
|
|
}
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
GetClientRect(&rc);
|
|
|
|
|
|
|
|
nRows = (rc.bottom - (YMARGIN * 2)) / (s.cy + YSPACE);
|
|
|
|
nCols = (rc.right - (2 * XMARGIN) - (5 * s.cx) - 17);
|
|
|
|
nCols /= (3 * (s.cx + 1));
|
|
|
|
if(nCols != 0)
|
|
|
|
{
|
|
|
|
nCols--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pRows != NULL)
|
|
|
|
{
|
|
|
|
*pRows = nRows;
|
|
|
|
}
|
|
|
|
if(pCols != NULL)
|
|
|
|
{
|
|
|
|
*pCols = nCols;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryView::Paint(HDC hDC)
|
|
|
|
{
|
|
|
|
RECT rwin;
|
|
|
|
SIZE s;
|
2007-02-28 20:20:18 +00:00
|
|
|
unsigned int nLines, nX, nY, nBytes, nFixedBytes;
|
2006-06-15 04:19:30 +00:00
|
|
|
uint32 nAddress;
|
2007-02-28 20:20:18 +00:00
|
|
|
Win32::CDeviceContext DeviceContext(hDC);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
|
|
|
GetClientRect(&rwin);
|
2007-02-28 20:20:18 +00:00
|
|
|
BitBlt(DeviceContext, 0, 0, rwin.right, rwin.bottom, NULL, 0, 0, WHITENESS);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
Win32::CFont Font(GetFont());
|
|
|
|
DeviceContext.SelectObject(Font);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
s = DeviceContext.GetFontSize(Font);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
GetRenderParams(s, nLines, nFixedBytes, nAddress);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
nBytes = nFixedBytes;
|
2006-06-15 04:19:30 +00:00
|
|
|
nY = YMARGIN;
|
2007-02-28 20:20:18 +00:00
|
|
|
|
|
|
|
for(unsigned int i = 0; i < nLines; i++)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
if(nAddress >= m_nSize)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if((nAddress + nBytes) >= m_nSize)
|
|
|
|
{
|
|
|
|
nBytes = (m_nSize - nAddress);
|
|
|
|
}
|
|
|
|
|
|
|
|
nX = XMARGIN;
|
2007-02-28 20:20:18 +00:00
|
|
|
DeviceContext.TextOut(nX, nY, lexical_cast_hex<tstring>(nAddress, 8).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
nX += (8 * s.cx) + 10;
|
2007-02-28 20:20:18 +00:00
|
|
|
|
|
|
|
for(unsigned int j = 0; j < nBytes; j++)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
2007-02-28 20:20:18 +00:00
|
|
|
DeviceContext.TextOut(nX, nY, lexical_cast_hex<tstring>(GetByte(nAddress + j), 2).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
nX += (2 * s.cx) + 3;
|
|
|
|
}
|
|
|
|
nX += (nFixedBytes - nBytes) * (2 * s.cx + 3);
|
|
|
|
|
|
|
|
nX += 10;
|
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
for(unsigned int j = 0; j < nBytes; j++)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
2007-02-28 20:20:18 +00:00
|
|
|
uint8 nValue;
|
|
|
|
char sValue[2];
|
|
|
|
|
|
|
|
nValue = GetByte(nAddress + j);
|
2006-06-15 04:19:30 +00:00
|
|
|
if(nValue < 0x20 || nValue > 0x7F)
|
|
|
|
{
|
|
|
|
nValue = '.';
|
|
|
|
}
|
|
|
|
sValue[0] = nValue;
|
|
|
|
sValue[1] = 0x00;
|
2007-02-28 20:20:18 +00:00
|
|
|
|
|
|
|
DeviceContext.TextOut(nX, nY, string_cast<tstring>(sValue).c_str());
|
2006-06-15 04:19:30 +00:00
|
|
|
nX += s.cx;
|
|
|
|
}
|
|
|
|
|
|
|
|
nY += (s.cy + YSPACE);
|
|
|
|
nAddress += nBytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryView::SetMemorySize(uint32 nSize)
|
|
|
|
{
|
|
|
|
m_nSize = nSize;
|
|
|
|
UpdateScrollRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
long CMemoryView::OnVScroll(unsigned int nType, unsigned int nTrackPos)
|
|
|
|
{
|
|
|
|
SCROLLINFO si;
|
|
|
|
int nOffset;
|
|
|
|
nOffset = (int)GetScrollOffset();
|
|
|
|
switch(nType)
|
|
|
|
{
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
nOffset++;
|
|
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
|
|
nOffset--;
|
|
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
nOffset += 10;
|
|
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
|
|
nOffset -= 10;
|
|
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
|
|
case SB_THUMBTRACK:
|
|
|
|
nOffset = GetScrollThumbPosition();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&si, 0, sizeof(SCROLLINFO));
|
|
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
|
|
si.nPos = nOffset;
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
SetScrollInfo(m_hWnd, SB_VERT, &si, TRUE);
|
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
UpdateCaretPosition();
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
Redraw();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CMemoryView::OnSize(unsigned int nType, unsigned int nX, unsigned int nY)
|
|
|
|
{
|
|
|
|
UpdateScrollRange();
|
2007-02-28 20:20:18 +00:00
|
|
|
UpdateCaretPosition();
|
2006-06-15 04:19:30 +00:00
|
|
|
CCustomDrawn::OnSize(nType, nX, nY);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CMemoryView::OnSetFocus()
|
|
|
|
{
|
2007-02-28 20:20:18 +00:00
|
|
|
Win32::CClientDeviceContext DeviceContext(m_hWnd);
|
|
|
|
Win32::CFont Font(GetFont());
|
|
|
|
|
|
|
|
CreateCaret(m_hWnd, NULL, 2, DeviceContext.GetFontHeight(Font));
|
|
|
|
ShowCaret(m_hWnd);
|
|
|
|
|
|
|
|
UpdateCaretPosition();
|
|
|
|
|
|
|
|
Redraw();
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-02-28 20:20:18 +00:00
|
|
|
long CMemoryView::OnKillFocus()
|
|
|
|
{
|
|
|
|
HideCaret(m_hWnd);
|
|
|
|
DestroyCaret();
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
long CMemoryView::OnMouseWheel(short nZ)
|
|
|
|
{
|
|
|
|
if(nZ < 0)
|
|
|
|
{
|
|
|
|
OnVScroll(SB_LINEDOWN, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OnVScroll(SB_LINEUP, 0);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-07-09 00:45:09 +00:00
|
|
|
long CMemoryView::OnLeftButtonDown(int nX, int nY)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
SetFocus();
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-02-28 20:20:18 +00:00
|
|
|
|
|
|
|
long CMemoryView::OnLeftButtonUp(int nX, int nY)
|
|
|
|
{
|
|
|
|
SIZE FontSize = Win32::CClientDeviceContext(m_hWnd).GetFontSize(Win32::CFont(GetFont()));
|
|
|
|
|
|
|
|
nY -= YMARGIN;
|
|
|
|
nX -= XMARGIN + (8 * FontSize.cx) + 10;
|
|
|
|
|
|
|
|
if(nY < 0) return FALSE;
|
|
|
|
if(nX < 0) return FALSE;
|
|
|
|
|
|
|
|
unsigned int nLine, nRow;
|
|
|
|
uint32 nAddress;
|
|
|
|
unsigned int nCols, nRows;
|
|
|
|
|
|
|
|
//Find selected line
|
|
|
|
nLine = nY / (FontSize.cy + YSPACE);
|
|
|
|
|
|
|
|
//Find selected row;
|
|
|
|
nRow = nX / ((2 * FontSize.cx) + 3);
|
|
|
|
|
|
|
|
GetRenderParams(FontSize, nCols, nRows, nAddress);
|
|
|
|
|
|
|
|
if(nRow >= nRows) return FALSE;
|
|
|
|
|
|
|
|
SetSelectionStart(nAddress + nRow + (nLine * nRows));
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
long CMemoryView::OnKeyDown(unsigned int nKey)
|
|
|
|
{
|
|
|
|
switch(nKey)
|
|
|
|
{
|
|
|
|
case VK_RIGHT:
|
|
|
|
SetSelectionStart(m_nSelectionStart + 1);
|
|
|
|
break;
|
|
|
|
case VK_LEFT:
|
|
|
|
SetSelectionStart(m_nSelectionStart - 1);
|
|
|
|
break;
|
|
|
|
case VK_UP:
|
|
|
|
case VK_DOWN:
|
|
|
|
{
|
|
|
|
unsigned int nCols;
|
|
|
|
GetVisibleRowsCols(NULL, &nCols);
|
|
|
|
SetSelectionStart(m_nSelectionStart + ((nKey == VK_UP) ? (-static_cast<int>(nCols)) : (nCols)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryView::SetSelectionStart(unsigned int nNewAddress)
|
|
|
|
{
|
|
|
|
if(static_cast<int>(nNewAddress) < 0) return;
|
|
|
|
if(nNewAddress >= m_nSize) return;
|
|
|
|
|
|
|
|
m_nSelectionStart = nNewAddress;
|
|
|
|
UpdateCaretPosition();
|
|
|
|
m_OnSelectionChange(m_nSelectionStart);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryView::UpdateCaretPosition()
|
|
|
|
{
|
|
|
|
Win32::CClientDeviceContext DeviceContext(m_hWnd);
|
|
|
|
Win32::CFont Font(GetFont());
|
|
|
|
|
|
|
|
unsigned int nLines, nBytes;
|
|
|
|
uint32 nAddress;
|
|
|
|
SIZE FontSize(DeviceContext.GetFontSize(Font));
|
|
|
|
|
|
|
|
GetRenderParams(
|
|
|
|
FontSize,
|
|
|
|
nLines,
|
|
|
|
nBytes,
|
|
|
|
nAddress);
|
|
|
|
|
|
|
|
if(
|
|
|
|
(m_nSelectionStart >= nAddress) &&
|
|
|
|
(m_nSelectionStart <= (nAddress + (nLines * nBytes)))
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int nX, nY;
|
|
|
|
unsigned int nSelectionStart = m_nSelectionStart - nAddress;
|
|
|
|
|
|
|
|
nX = XMARGIN + (8 * FontSize.cx) + 10 + (nSelectionStart % nBytes) * ((2 * FontSize.cx) + 3);
|
|
|
|
nY = YMARGIN + (FontSize.cy + YSPACE) * (nSelectionStart / nBytes);
|
|
|
|
SetCaretPos(nX, nY);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetCaretPos(-20, -20);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryView::GetRenderParams(const SIZE& FontSize, unsigned int& nLines, unsigned int& nFixedBytes, uint32& nAddress)
|
|
|
|
{
|
|
|
|
RECT ClientRect(GetClientRect());
|
|
|
|
|
|
|
|
nLines = (ClientRect.bottom - (YMARGIN * 2)) / (FontSize.cy + YSPACE);
|
|
|
|
|
|
|
|
nFixedBytes = ClientRect.right - (2 * XMARGIN) - (5 * FontSize.cx) - 17;
|
|
|
|
nFixedBytes /= (3 * (FontSize.cx + 1));
|
|
|
|
if(nFixedBytes != 0)
|
|
|
|
{
|
|
|
|
nFixedBytes--;
|
|
|
|
}
|
|
|
|
//nFixedBytes &= ~(0x0F);
|
|
|
|
//nBytes = nFixedBytes;
|
|
|
|
|
|
|
|
nLines++;
|
|
|
|
|
|
|
|
nAddress = GetScrollOffset() * nFixedBytes;
|
|
|
|
}
|