procedure UpdateListbox(ListBoxHex : HWND;
BaseAddress : pointer;
BlockSize : DWORD);
{ displays a memory block in hex }
const
SPACE = $20; { ASCII space character }
HEX_DUMP_WIDTH = 16; { number of hex values per line }
HexDigits : packed array[0..$F] of char = '0123456789ABCDEF';
var
{ variables related to the formatting of hex strings to be displayed }
Buf : packed array[0..127] of char; { one output line }
HexPtr : ^char; { pointer to hex area of line buffer }
CharPtr : ^char; { pointer to character area of line buffer }
p : PBYTE; { used to walk the memory block }
I : DWORD;
b : byte;
begin
{ reset the contents of the hex view listbox. Minimize the flicker by }
{ turning listbox redrawing off while we change its settings. }
SendMessage(ListBoxHex, WM_SETREDRAW, ord(FALSE), 0); { redraw off }
I := 0;
while I < BlockSize do
begin
FillMemory(@Buf, sizeof(Buf), SPACE); { space out the buffer }
{ place the offset at the beginning of the line }
StrFmt(Buf, ' %p : ', [pointer(pchar(BaseAddress) + I)]);
{ calculate the pointer value to the start of the hex area in buf }
HexPtr := pointer(pchar(@Buf) + lstrlen(Buf));
{ calculate the pointer value to the start of the character area }
CharPtr := pointer(pchar(HexPtr) + (HEX_DUMP_WIDTH * 3) + 1);
repeat
pchar(p) := pchar(BaseAddress) + I; { current byte pointer }
HexPtr^ := HexDigits[p^ shr 4]; { first nibble }
inc(HexPtr);
{ following lines to demonstrate the problem by comparison }
if I = BlockSize - 1 then DebugBreak;
b := p^;
b := b and $F;
HexPtr^ := HexDigits[b];
{ problematic statement - occasionally causes an access violation on the last byte of the memory block }
HexPtr^ := HexDigits[p^ and $F]; { second nibble }
inc(HexPtr);
{ increment HexPtr again to leave a space between bytes }
inc(HexPtr);
{ if the byte is a printable character then just place it in the char }
{ area of the buffer, otherwise put a dot instead }
if p^ in [32..126]
then CharPtr^ := char(p^) { the byte is printable }
else CharPtr^ := '.'; { not printable, put a dot }
inc(CharPtr);
{ put an extra space between the first and second half of the hex area }
if I mod HEX_DUMP_WIDTH = (HEX_DUMP_WIDTH div 2) - 1 then Inc(HexPtr);
inc(I);
until (I >= BlockSize) or ((I mod HEX_DUMP_WIDTH) = 0);
CharPtr^ := #0; { null terminate the buffer }
SendMessage(ListBoxHex, LB_ADDSTRING, 0, ptruint(@Buf)); { add to listbox }
end;
SendMessage(ListBoxHex, WM_SETREDRAW, ord(TRUE), 0); { redraw on }
end;