33 WNDCLASSEX c = {
sizeof(c) };
35 c.style = CS_GLOBALCLASS;
38 c.cbWndExtra =
sizeof(PVOID);
41 c.hCursor = LoadCursor(NULL, IDC_ARROW);
42 c.hbrBackground = NULL;
43 c.lpszMenuName = NULL;
47 if (!RegisterClassEx(&c))
97 if (!Context->UserBuffer && Context->Data)
PhFree(Context->Data);
98 if (Context->CharBuffer)
PhFree(Context->CharBuffer);
99 if (Context->Font) DeleteObject(Context->Font);
114 if (uMsg == WM_CREATE)
117 SetWindowLongPtr(hwnd, 0, (LONG_PTR)context);
121 return DefWindowProc(hwnd, uMsg, wParam, lParam);
127 context->
Font = CreateFont(-12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L
"Courier New");
137 PAINTSTRUCT paintStruct;
140 if (hdc = BeginPaint(hwnd, &paintStruct))
143 EndPaint(hwnd, &paintStruct);
168 SHORT scrollRequest = LOWORD(wParam);
169 LONG currentPosition;
170 LONG originalTopIndex;
171 SCROLLINFO scrollInfo = {
sizeof(scrollInfo) };
173 originalTopIndex = context->
TopIndex;
175 scrollInfo.fMask = SIF_TRACKPOS;
176 GetScrollInfo(hwnd, SB_VERT, &scrollInfo);
177 currentPosition = scrollInfo.nTrackPos;
185 switch (scrollRequest)
240 SHORT wheelDelta = GET_WHEEL_DELTA_WPARAM(wParam);
244 ULONG wheelScrollLines;
246 if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &wheelScrollLines, 0))
247 wheelScrollLines = 3;
269 if (wParam != VK_ESCAPE)
270 return DLGC_WANTALLKEYS;
276 ULONG flags = (ULONG)wParam;
279 cursorPos.x = (
LONG)(SHORT)LOWORD(lParam);
280 cursorPos.y = (
LONG)(SHORT)HIWORD(lParam);
288 if (wParam & MK_SHIFT)
305 SetCaretPos(point.x, point.y);
307 if (flags & MK_SHIFT)
318 if (!(flags & MK_SHIFT))
320 if (DragDetect(hwnd, cursorPos))
355 ULONG flags = (ULONG)wParam;
358 cursorPos.x = (
LONG)(SHORT)LOWORD(lParam);
359 cursorPos.y = (
LONG)(SHORT)HIWORD(lParam);
373 GetClientRect(hwnd, &rect);
375 if (!PtInRect(&rect, cursorPos))
379 SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
382 else if (cursorPos.y > rect.bottom)
384 SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
385 cursorPos.y = rect.bottom - 1;
389 oldSelEnd = context->
SelEnd;
403 if (context->
SelEnd != oldSelEnd)
410 ULONG c = (ULONG)wParam;
417 if (GetKeyState(VK_CONTROL) < 0)
463 if ((c >=
'0' && c <=
'9') || (c >=
'a' && c <=
'f'))
495 ULONG vk = (ULONG)wParam;
496 BOOLEAN shift = GetKeyState(VK_SHIFT) < 0;
498 BOOLEAN noScrollIntoView =
FALSE;
527 noScrollIntoView =
TRUE;
554 noScrollIntoView =
TRUE;
581 noScrollIntoView =
TRUE;
607 noScrollIntoView =
TRUE;
616 SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
628 SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
630 noScrollIntoView =
TRUE;
638 SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
650 SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
652 noScrollIntoView =
TRUE;
660 if (GetKeyState(VK_CONTROL) < 0)
662 SendMessage(hwnd, WM_VSCROLL, SB_THUMBTRACK, 0);
682 if (GetKeyState(VK_CONTROL) < 0)
684 SendMessage(hwnd, WM_VSCROLL, SB_THUMBTRACK, 0);
695 noScrollIntoView =
TRUE;
704 if (GetKeyState(VK_CONTROL) < 0)
707 SendMessage(hwnd, WM_VSCROLL,
732 if (GetKeyState(VK_CONTROL) < 0)
738 SendMessage(hwnd, WM_VSCROLL, 0, 0);
742 SendMessage(hwnd, WM_VSCROLL,
758 noScrollIntoView =
TRUE;
822 PULONG length = (PULONG)wParam;
825 *length = context->
Length;
827 return (LPARAM)context->
Data;
836 if (selEnd > context->
Length)
855 if (bytesPerRow >= 4)
869 return DefWindowProc(hwnd, uMsg, wParam, lParam);
875 _Inout_ PWCHAR Buffer,
886 TextOut(hdc, *X, *Y, Buffer, 3);
887 *X += Context->NullWidth * 3;
890 if (*N == Context->BytesPerRow)
893 *X = Context->HexOffset;
894 *Y += Context->LineHeight;
910 TextOut(hdc, *X, *Y, &c, 1);
911 *X += Context->NullWidth;
914 if (*N == Context->BytesPerRow)
917 *X = Context->AsciiOffset;
918 *Y += Context->LineHeight;
931 color = GetSysColor(COLOR_HIGHLIGHT);
933 g = (UCHAR)(color >> 8);
934 b = (UCHAR)(color >> 16);
960 BOOLEAN freeHdc =
FALSE;
966 hdc = CreateCompatibleDC(hdc);
967 SelectObject(hdc, Context->Font);
971 GetClientRect(hwnd, &clientRect);
972 GetCharWidth(hdc,
'0',
'0', &Context->NullWidth);
973 GetTextExtentPoint32(hdc, L
"0", 1, &size);
974 Context->LineHeight = size.cy;
976 Context->HexOffset = Context->ShowAddress ? (Context->AddressIsWide ? Context->NullWidth * 9 : Context->NullWidth * 5) : 0;
977 Context->AsciiOffset = Context->HexOffset + (Context->ShowHex ? (Context->BytesPerRow * 3 * Context->NullWidth) : 0);
979 Context->LinesPerPage = clientRect.bottom / Context->LineHeight;
980 Context->HalfPage =
FALSE;
982 if (Context->LinesPerPage * Context->BytesPerRow > Context->Length)
984 Context->LinesPerPage = (Context->Length + Context->BytesPerRow / 2) / Context->BytesPerRow;
986 if (Context->Length % Context->BytesPerRow != 0)
988 Context->HalfPage =
TRUE;
989 Context->LinesPerPage++;
1000 _In_ PAINTSTRUCT *PaintStruct,
1006 HBITMAP bufferBitmap;
1007 HBITMAP oldBufferBitmap;
1012 ULONG requiredBufferLength;
1015 GetClientRect(hwnd, &clientRect);
1017 bufferDc = CreateCompatibleDC(hdc);
1018 bufferBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom);
1019 oldBufferBitmap = SelectObject(bufferDc, bufferBitmap);
1021 SetDCBrushColor(bufferDc, GetSysColor(COLOR_WINDOW));
1022 FillRect(bufferDc, &clientRect, GetStockObject(DC_BRUSH));
1023 SelectObject(bufferDc, Context->Font);
1024 SetBoundsRect(bufferDc, &clientRect, DCB_DISABLE);
1026 requiredBufferLength = (max(8, Context->BytesPerRow * 3) + 1) *
sizeof(WCHAR);
1028 if (Context->CharBufferLength < requiredBufferLength)
1030 if (Context->CharBuffer)
1031 PhFree(Context->CharBuffer);
1033 Context->CharBuffer = PhAllocate(requiredBufferLength);
1034 Context->CharBufferLength = requiredBufferLength;
1035 buffer = Context->CharBuffer;
1038 buffer = Context->CharBuffer;
1043 if (Context->Update)
1046 Context->Update =
FALSE;
1050 height = (clientRect.bottom + Context->LineHeight - 1) / Context->LineHeight * Context->LineHeight;
1052 if (Context->ShowAddress)
1060 format.
Width = Context->AddressIsWide ? 8 : 4;
1062 w = Context->AddressIsWide ? 8 : 4;
1065 rect.left = Context->AddressOffset;
1068 for (i = Context->TopIndex; i < Context->Length && rect.top < height; i += Context->BytesPerRow)
1072 DrawText(bufferDc, buffer, w, &rect, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP);
1073 rect.top += Context->LineHeight;
1077 if (Context->ShowHex)
1082 x = Context->HexOffset;
1088 if (Context->SelStart != -1)
1090 COLORREF highlightColor;
1095 highlightColor = GetSysColor(COLOR_HIGHLIGHT);
1099 selStart = Context->SelStart;
1100 selEnd = Context->SelEnd;
1102 if (selStart > selEnd)
1111 if (selStart >= Context->Length)
1112 selStart = Context->Length - 1;
1113 if (selEnd > Context->Length)
1114 selEnd = Context->Length;
1118 for (i = Context->TopIndex; i < selStart && y < height; i++)
1120 PhpPrintHex(bufferDc, Context, buffer, Context->Data[i], &x, &y, &n);
1125 SetTextColor(bufferDc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1126 SetBkColor(bufferDc, highlightColor);
1128 for (; i < selEnd && i < Context->Length && y < height; i++)
1130 PhpPrintHex(bufferDc, Context, buffer, Context->Data[i], &x, &y, &n);
1135 SetTextColor(bufferDc, GetSysColor(COLOR_WINDOWTEXT));
1136 SetBkColor(bufferDc, GetSysColor(COLOR_WINDOW));
1138 for (; i < Context->Length && y < height; i++)
1140 PhpPrintHex(bufferDc, Context, buffer, Context->Data[i], &x, &y, &n);
1145 i = Context->TopIndex;
1147 while (i < Context->Length && rect.top < height)
1151 for (n = 0; n < Context->BytesPerRow && i < Context->Length; n++)
1153 TO_HEX(p, Context->Data[i]);
1158 while (n < Context->BytesPerRow)
1167 DrawText(bufferDc, buffer, Context->BytesPerRow * 3, &rect, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP);
1168 rect.top += Context->LineHeight;
1173 if (Context->ShowAscii)
1178 x = Context->AsciiOffset;
1184 if (Context->SelStart != -1)
1186 COLORREF highlightColor;
1191 highlightColor = GetSysColor(COLOR_HIGHLIGHT);
1195 selStart = Context->SelStart;
1196 selEnd = Context->SelEnd;
1198 if (selStart > selEnd)
1207 if (selStart >= Context->Length)
1208 selStart = Context->Length - 1;
1209 if (selEnd > Context->Length)
1210 selEnd = Context->Length;
1214 for (i = Context->TopIndex; i < selStart && y < height; i++)
1216 PhpPrintAscii(bufferDc, Context, Context->Data[i], &x, &y, &n);
1221 SetTextColor(bufferDc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1222 SetBkColor(bufferDc, highlightColor);
1224 for (; i < selEnd && i < Context->Length && y < height; i++)
1226 PhpPrintAscii(bufferDc, Context, Context->Data[i], &x, &y, &n);
1231 SetTextColor(bufferDc, GetSysColor(COLOR_WINDOWTEXT));
1232 SetBkColor(bufferDc, GetSysColor(COLOR_WINDOW));
1234 for (; i < Context->Length && y < height; i++)
1236 PhpPrintAscii(bufferDc, Context, Context->Data[i], &x, &y, &n);
1241 i = Context->TopIndex;
1243 while (i < Context->Length && rect.top < height)
1247 for (n = 0; n < Context->BytesPerRow && i < Context->Length; n++)
1249 *p++ =
IS_PRINTABLE(Context->Data[i]) ? Context->Data[i] :
'.';
1253 DrawText(bufferDc, buffer, n, &rect, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP);
1254 rect.top += Context->LineHeight;
1260 BitBlt(hdc, 0, 0, clientRect.right, clientRect.bottom, bufferDc, 0, 0, SRCCOPY);
1261 SelectObject(bufferDc, oldBufferBitmap);
1262 DeleteObject(bufferBitmap);
1271 SCROLLINFO si = {
sizeof(si) };
1275 si.nMax = (Context->Length / Context->BytesPerRow) - 1;
1276 si.nPage = Context->LinesPerPage;
1277 si.nPos = Context->TopIndex / Context->BytesPerRow;
1278 SetScrollInfo(hwnd, SB_VERT, &si,
TRUE);
1280 if (si.nMax > (
LONG)si.nPage)
1281 EnableScrollBar(hwnd, SB_VERT, ESB_ENABLE_BOTH);
1299 CreateCaret(hwnd, NULL, Context->NullWidth * (Context->AddressIsWide ? 8 : 4), Context->LineHeight);
1308 CreateCaret(hwnd, NULL, Context->NullWidth, Context->LineHeight);
1321 x = (Position - Context->TopIndex) % Context->BytesPerRow;
1322 y = (Position - Context->TopIndex) / Context->BytesPerRow;
1324 switch (Context->CurrentMode)
1332 x *= Context->NullWidth * 3;
1333 x += Context->HexOffset;
1337 x *= Context->NullWidth * 3;
1338 x += Context->NullWidth;
1339 x += Context->HexOffset;
1343 x *= Context->NullWidth;
1344 x += Context->AsciiOffset;
1348 Context->EditPosition.x = x;
1349 Context->EditPosition.y = y * Context->LineHeight;
1351 GetClientRect(hwnd, &rect);
1353 if (PtInRect(&rect, Context->EditPosition))
1355 SetCaretPos(Context->EditPosition.x, Context->EditPosition.y);
1370 Y /= Context->LineHeight;
1372 if (Y < 0 || Y >= Context->LinesPerPage)
1379 if (Y * Context->BytesPerRow >= Context->Length)
1386 X += Context->NullWidth;
1387 X /= Context->NullWidth;
1389 if (Context->ShowAddress && X <= (Context->AddressIsWide ? 8 : 4))
1391 Context->CurrentAddress = Context->TopIndex + Context->BytesPerRow * Y;
1399 xp = Context->HexOffset / Context->NullWidth + Context->BytesPerRow * 3;
1401 if (Context->ShowHex && X < xp)
1406 Context->CurrentAddress = Context->TopIndex +
1407 Context->BytesPerRow * Y +
1408 (X - (Context->HexOffset / Context->NullWidth)) / 3;
1418 xp = Context->AsciiOffset / Context->NullWidth + Context->BytesPerRow;
1420 if (Context->ShowAscii && X * Context->NullWidth >= Context->AsciiOffset && X <= xp)
1422 Context->CurrentAddress = Context->TopIndex +
1423 Context->BytesPerRow * Y +
1424 (X - (Context->AsciiOffset / Context->NullWidth));
1443 switch (Context->CurrentMode)
1446 Context->CurrentAddress += Y * Context->BytesPerRow;
1452 Context->CurrentAddress--;
1453 Context->CurrentAddress += Y * Context->BytesPerRow;
1459 Context->CurrentAddress++;
1460 Context->CurrentAddress += Y * Context->BytesPerRow;
1463 Context->CurrentAddress += X;
1464 Context->CurrentAddress += Y * Context->BytesPerRow;
1468 if (Context->CurrentAddress < 0)
1469 Context->CurrentAddress = 0;
1471 if (Context->CurrentAddress >= Context->Length)
1473 Context->CurrentAddress -= X;
1474 Context->CurrentAddress -= Y * Context->BytesPerRow;
1477 Context->NoAddressChange =
TRUE;
1479 if (Context->CurrentAddress < Context->TopIndex)
1480 SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
1481 if (Context->CurrentAddress >= Context->TopIndex + Context->LinesPerPage * Context->BytesPerRow)
1482 SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
1484 Context->NoAddressChange =
FALSE;
1496 Context->SelStart = S;
1497 Context->SelEnd = E;
1500 if (S != -1 && E != -1)
1502 Context->CurrentAddress = S;
1506 if (Context->EditPosition.x == 0 && Context->ShowAddress)
1511 SetCaretPos(Context->EditPosition.x, Context->EditPosition.y);
1522 if (Position < Context->TopIndex || Position > Context->TopIndex + Context->LinesPerPage * Context->BytesPerRow)
1524 Context->TopIndex = Position / Context->BytesPerRow * Context->BytesPerRow;
1525 Context->TopIndex -= Context->LinesPerPage / 3 * Context->BytesPerRow;
1527 if (Context->TopIndex < 0)
1528 Context->TopIndex = 0;
1530 if (Context->Length >= Context->LinesPerPage * Context->BytesPerRow)
1532 if (Context->TopIndex > Context->Length - Context->LinesPerPage * Context->BytesPerRow)
1533 Context->TopIndex = Context->Length - Context->LinesPerPage * Context->BytesPerRow;
1546 if (Context->AllowLengthChange)
1548 Context->CurrentAddress = Context->SelStart;
1560 if (OpenClipboard(hwnd))
1567 ULONG length = Context->SelEnd - Context->SelStart;
1568 HGLOBAL binaryMemory;
1571 binaryMemory = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, length);
1575 PUCHAR p = GlobalLock(binaryMemory);
1576 memcpy(p, &Context->Data[Context->SelStart], length);
1577 GlobalUnlock(binaryMemory);
1579 hexMemory = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (length * 3 + 1) *
sizeof(WCHAR));
1586 pw = GlobalLock(hexMemory);
1588 for (i = 0; i < length; i++)
1590 TO_HEX(pw, Context->Data[Context->SelStart + i]);
1595 GlobalUnlock(hexMemory);
1597 SetClipboardData(CF_UNICODETEXT, hexMemory);
1600 SetClipboardData(RegisterClipboardFormat(L
"BinaryData"), binaryMemory);
1605 ULONG length = Context->SelEnd - Context->SelStart;
1606 HGLOBAL binaryMemory;
1607 HGLOBAL asciiMemory;
1609 binaryMemory = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, length);
1610 asciiMemory = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, length + 1);
1614 PUCHAR p = GlobalLock(binaryMemory);
1615 memcpy(p, &Context->Data[Context->SelStart], length);
1616 GlobalUnlock(binaryMemory);
1622 p = GlobalLock(asciiMemory);
1623 memcpy(p, &Context->Data[Context->SelStart], length);
1625 for (i = 0; i < length; i++)
1633 GlobalUnlock(asciiMemory);
1635 SetClipboardData(CF_TEXT, asciiMemory);
1638 SetClipboardData(RegisterClipboardFormat(L
"BinaryData"), binaryMemory);
1651 if (Context->AllowLengthChange)
1664 if (OpenClipboard(hwnd))
1668 memory = GetClipboardData(RegisterClipboardFormat(L
"BinaryData"));
1671 memory = GetClipboardData(CF_TEXT);
1675 PUCHAR p = GlobalLock(memory);
1676 ULONG length = (ULONG)GlobalSize(memory);
1678 ULONG oldCurrentAddress = Context->CurrentAddress;
1682 if (Context->AllowLengthChange)
1684 if (Context->SelStart == -1)
1686 if (Context->CurrentMode ==
EDIT_LOW)
1687 Context->CurrentAddress++;
1689 paste = Context->CurrentAddress;
1694 paste = Context->SelStart;
1702 if (Context->SelStart == -1)
1704 if (Context->CurrentMode ==
EDIT_LOW)
1705 Context->CurrentAddress++;
1707 paste = Context->CurrentAddress;
1711 paste = Context->SelStart;
1714 if (length > Context->Length - paste)
1715 length = Context->Length - paste;
1718 memcpy(&Context->Data[paste], p, length);
1719 GlobalUnlock(memory);
1721 Context->CurrentAddress = oldCurrentAddress;
1734 Context->SelStart = 0;
1735 Context->SelEnd = Context->Length;
1753 if (Context->SelStart > Context->SelEnd)
1757 t = Context->SelEnd;
1758 Context->SelEnd = Context->SelStart;
1759 Context->SelStart = t;
1770 if (Context->AllowLengthChange && Context->Length > 0)
1772 PUCHAR p = PhAllocate(Context->Length - (E - S) + 1);
1774 memcpy(p, Context->Data, S);
1776 if (S < Context->Length - (E - S))
1777 memcpy(&p[S], &Context->Data[E], Context->Length - E);
1782 Context->Length -= E - S;
1784 if (Context->CurrentAddress > Context->Length)
1786 Context->CurrentAddress = Context->Length;
1790 Context->Update =
TRUE;
1801 if (Context->AllowLengthChange)
1803 PUCHAR p = PhAllocate(Context->Length + L);
1805 memset(p, 0, Context->Length + L);
1806 memcpy(p, Context->Data, S);
1807 memcpy(&p[S + L], &Context->Data[S], Context->Length - S);
1812 Context->Length += L;
1814 Context->Update =
TRUE;
1825 Context->Data = Data;
1827 Context->Length = Length;
1828 Context->CurrentAddress = 0;
1829 Context->EditPosition.x = Context->EditPosition.y = 0;
1831 Context->TopIndex = 0;
1832 Context->Update =
TRUE;
1834 Context->UserBuffer =
TRUE;
1835 Context->AllowLengthChange =
FALSE;
1845 if (Context->Data)
PhFree(Context->Data);
1846 Context->Data = PhAllocate(Length);
1847 memcpy(Context->Data, Data, Length);
1849 Context->UserBuffer =
FALSE;
1850 Context->AllowLengthChange =
TRUE;