push 22a06a4565db8671d48dc7f2781fb649355c721f
[wine/hacks.git] / programs / regedit / hexedit.c
blob5e770c92d8abde8a5140110279c07f56099e4dbb
1 /*
2 * Hex Edit control
4 * Copyright 2005 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * TODO:
21 * - Selection support
22 * - Cut, copy and paste
23 * - Mouse support
26 #include <stdarg.h>
27 #include <string.h>
28 #include <assert.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "winnls.h"
35 #include "commctrl.h"
37 #include "main.h"
39 /* spaces dividing hex and ASCII */
40 #define DIV_SPACES 4
42 typedef struct tagHEXEDIT_INFO
44 HWND hwndSelf;
45 HFONT hFont;
46 BOOL bFocus : 1;
47 BOOL bFocusHex : 1; /* TRUE if focus is on hex, FALSE if focus on ASCII */
48 BOOL bInsert : 1; /* insert mode if TRUE, overwrite mode if FALSE */
49 INT nHeight; /* height of text */
50 INT nCaretPos; /* caret pos in nibbles */
51 BYTE *pData;
52 INT cbData;
53 INT nBytesPerLine; /* bytes of hex to display per line of the control */
54 INT nScrollPos; /* first visible line */
55 } HEXEDIT_INFO;
57 static inline LRESULT HexEdit_SetFont (HEXEDIT_INFO *infoPtr, HFONT hFont, BOOL redraw);
59 static inline BYTE hexchar_to_byte(TCHAR ch)
61 if (ch >= '0' && ch <= '9')
62 return ch - '0';
63 else if (ch >= 'a' && ch <= 'f')
64 return ch - 'a' + 10;
65 else if (ch >= 'A' && ch <= 'F')
66 return ch - 'A' + 10;
67 else
68 return -1;
71 static LPTSTR HexEdit_GetLineText(BYTE *pData, LONG cbData, LONG pad)
73 LPTSTR lpszLine = HeapAlloc(GetProcessHeap(), 0,
74 (cbData * 3 + pad * 3 + DIV_SPACES + cbData + 1) * sizeof(TCHAR));
75 LONG i;
77 if (!lpszLine)
78 return NULL;
80 for (i = 0; i < cbData; i++)
81 wsprintf(lpszLine + i*3, TEXT("%02X "), pData[i]);
82 for (i = 0; i < pad * 3; i++)
83 lpszLine[cbData * 3 + i] = ' ';
85 for (i = 0; i < DIV_SPACES; i++)
86 lpszLine[cbData * 3 + pad * 3 + i] = ' ';
88 /* attempt an ASCII representation if the characters are printable,
89 * otherwise display a '.' */
90 for (i = 0; i < cbData; i++)
92 /* (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER) */
93 if (isprint(pData[i]))
94 lpszLine[cbData * 3 + pad * 3 + DIV_SPACES + i] = pData[i];
95 else
96 lpszLine[cbData * 3 + pad * 3 + DIV_SPACES + i] = '.';
98 lpszLine[cbData * 3 + pad * 3 + DIV_SPACES + cbData] = 0;
99 return lpszLine;
102 static void
103 HexEdit_Paint(HEXEDIT_INFO *infoPtr)
105 PAINTSTRUCT ps;
106 HDC hdc = BeginPaint(infoPtr->hwndSelf, &ps);
107 INT nXStart, nYStart;
108 COLORREF clrOldText;
109 HFONT hOldFont;
110 BYTE *pData;
111 INT iMode;
112 LONG lByteOffset = infoPtr->nScrollPos * infoPtr->nBytesPerLine;
114 /* Make a gap from the frame */
115 nXStart = GetSystemMetrics(SM_CXBORDER);
116 nYStart = GetSystemMetrics(SM_CYBORDER);
118 if (GetWindowLong(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
119 clrOldText = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
120 else
121 clrOldText = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
123 iMode = SetBkMode(hdc, TRANSPARENT);
124 hOldFont = SelectObject(hdc, infoPtr->hFont);
126 for (pData = infoPtr->pData + lByteOffset; pData < infoPtr->pData + infoPtr->cbData; pData += infoPtr->nBytesPerLine)
128 LPTSTR lpszLine;
129 LONG nLineLen = min((LONG)((infoPtr->pData + infoPtr->cbData) - pData),
130 infoPtr->nBytesPerLine);
132 lpszLine = HexEdit_GetLineText(pData, nLineLen, infoPtr->nBytesPerLine - nLineLen);
134 /* FIXME: draw hex <-> ASCII mapping highlighted? */
135 TextOut(hdc, nXStart, nYStart, lpszLine, infoPtr->nBytesPerLine * 3 + DIV_SPACES + nLineLen);
137 nYStart += infoPtr->nHeight;
138 HeapFree(GetProcessHeap(), 0, lpszLine);
141 SelectObject(hdc, hOldFont);
142 SetBkMode(hdc, iMode);
143 SetTextColor(hdc, clrOldText);
145 EndPaint(infoPtr->hwndSelf, &ps);
148 static void
149 HexEdit_UpdateCaret(HEXEDIT_INFO *infoPtr)
151 HDC hdc;
152 HFONT hOldFont;
153 SIZE size;
154 INT nCaretBytePos = infoPtr->nCaretPos/2;
155 INT nByteLinePos = nCaretBytePos % infoPtr->nBytesPerLine;
156 INT nLine = nCaretBytePos / infoPtr->nBytesPerLine;
157 LONG nLineLen = min(infoPtr->cbData - nLine * infoPtr->nBytesPerLine, infoPtr->nBytesPerLine);
158 LPTSTR lpszLine = HexEdit_GetLineText(infoPtr->pData + nLine * infoPtr->nBytesPerLine, nLineLen, infoPtr->nBytesPerLine - nLineLen);
159 INT nCharOffset;
161 /* calculate offset of character caret is on in the line */
162 if (infoPtr->bFocusHex)
163 nCharOffset = nByteLinePos*3 + infoPtr->nCaretPos % 2;
164 else
165 nCharOffset = infoPtr->nBytesPerLine*3 + DIV_SPACES + nByteLinePos;
167 hdc = GetDC(infoPtr->hwndSelf);
168 hOldFont = SelectObject(hdc, infoPtr->hFont);
170 GetTextExtentPoint32(hdc, lpszLine, nCharOffset, &size);
172 SelectObject(hdc, hOldFont);
173 ReleaseDC(infoPtr->hwndSelf, hdc);
175 if (!nLineLen) size.cx = 0;
177 HeapFree(GetProcessHeap(), 0, lpszLine);
179 SetCaretPos(
180 GetSystemMetrics(SM_CXBORDER) + size.cx,
181 GetSystemMetrics(SM_CYBORDER) + (nLine - infoPtr->nScrollPos) * infoPtr->nHeight);
184 static void
185 HexEdit_UpdateScrollbars(HEXEDIT_INFO *infoPtr)
187 RECT rcClient;
188 INT nLines = infoPtr->cbData / infoPtr->nBytesPerLine;
189 INT nVisibleLines;
190 SCROLLINFO si;
192 GetClientRect(infoPtr->hwndSelf, &rcClient);
193 InflateRect(&rcClient, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
195 nVisibleLines = (rcClient.bottom - rcClient.top) / infoPtr->nHeight;
196 si.cbSize = sizeof(si);
197 si.fMask = SIF_RANGE | SIF_PAGE;
198 si.nMin = 0;
199 si.nMax = max(nLines - nVisibleLines, nLines);
200 si.nPage = nVisibleLines;
201 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, TRUE);
204 static void
205 HexEdit_EnsureVisible(HEXEDIT_INFO *infoPtr, INT nCaretPos)
207 INT nLine = nCaretPos / (2 * infoPtr->nBytesPerLine);
208 SCROLLINFO si;
210 si.cbSize = sizeof(si);
211 si.fMask = SIF_POS | SIF_PAGE;
212 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
213 if (nLine < si.nPos)
214 si.nPos = nLine;
215 else if (nLine >= si.nPos + si.nPage)
216 si.nPos = nLine - si.nPage + 1;
217 else
218 return;
219 si.fMask = SIF_POS;
221 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, FALSE);
222 SendMessage(infoPtr->hwndSelf, WM_VSCROLL, MAKELONG(SB_THUMBPOSITION, 0), 0);
226 static LRESULT
227 HexEdit_SetData(HEXEDIT_INFO *infoPtr, INT cbData, const BYTE *pData)
229 HeapFree(GetProcessHeap(), 0, infoPtr->pData);
230 infoPtr->cbData = 0;
232 infoPtr->pData = HeapAlloc(GetProcessHeap(), 0, cbData);
233 if (infoPtr->pData)
235 memcpy(infoPtr->pData, pData, cbData);
236 infoPtr->cbData = cbData;
238 infoPtr->nCaretPos = 0;
239 HexEdit_UpdateScrollbars(infoPtr);
240 HexEdit_UpdateCaret(infoPtr);
241 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
242 return TRUE;
244 return FALSE;
247 static LRESULT
248 HexEdit_GetData(HEXEDIT_INFO *infoPtr, INT cbData, BYTE *pData)
250 if (pData)
251 memcpy(pData, infoPtr->pData, min(cbData, infoPtr->cbData));
252 return infoPtr->cbData;
255 static inline LRESULT
256 HexEdit_Char (HEXEDIT_INFO *infoPtr, TCHAR ch)
258 INT nCaretBytePos = infoPtr->nCaretPos/2;
260 assert(nCaretBytePos >= 0);
262 /* backspace is special */
263 if (ch == '\b')
265 if (infoPtr->nCaretPos == 0)
266 return 0;
268 /* if at end of byte then delete the whole byte */
269 if (infoPtr->bFocusHex && (infoPtr->nCaretPos % 2 == 0))
271 memmove(infoPtr->pData + nCaretBytePos - 1,
272 infoPtr->pData + nCaretBytePos,
273 infoPtr->cbData - nCaretBytePos);
274 infoPtr->cbData--;
275 infoPtr->nCaretPos -= 2; /* backtrack two nibble */
277 else /* blank upper nibble */
279 infoPtr->pData[nCaretBytePos] &= 0x0f;
280 infoPtr->nCaretPos--; /* backtrack one nibble */
283 else
285 if (infoPtr->bFocusHex && hexchar_to_byte(ch) == (BYTE)-1)
287 MessageBeep(MB_ICONWARNING);
288 return 0;
291 if ((infoPtr->bInsert && (infoPtr->nCaretPos % 2 == 0)) || (nCaretBytePos >= infoPtr->cbData))
293 /* make room for another byte */
294 infoPtr->cbData++;
295 infoPtr->pData = HeapReAlloc(GetProcessHeap(), 0, infoPtr->pData, infoPtr->cbData + 1);
296 if (!infoPtr->pData) return 0;
297 /* move everything after caret up one byte */
298 memmove(infoPtr->pData + nCaretBytePos + 1,
299 infoPtr->pData + nCaretBytePos,
300 infoPtr->cbData - nCaretBytePos);
301 /* zero new byte */
302 infoPtr->pData[nCaretBytePos] = 0x0;
305 /* overwrite a byte */
307 assert(nCaretBytePos < infoPtr->cbData);
309 if (infoPtr->bFocusHex)
311 BYTE orig_byte = infoPtr->pData[nCaretBytePos];
312 BYTE digit = hexchar_to_byte(ch);
313 if (infoPtr->nCaretPos % 2) /* set low nibble */
314 infoPtr->pData[nCaretBytePos] = (orig_byte & 0xf0) | digit;
315 else /* set high nibble */
316 infoPtr->pData[nCaretBytePos] = (orig_byte & 0x0f) | digit << 4;
317 infoPtr->nCaretPos++; /* advance one nibble */
319 else
321 infoPtr->pData[nCaretBytePos] = (BYTE)ch;
322 infoPtr->nCaretPos += 2; /* advance two nibbles */
326 HexEdit_UpdateScrollbars(infoPtr);
327 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
328 HexEdit_UpdateCaret(infoPtr);
329 HexEdit_EnsureVisible(infoPtr, infoPtr->nCaretPos);
330 return 0;
333 static inline LRESULT
334 HexEdit_Create (HEXEDIT_INFO *infoPtr, LPCREATESTRUCT lpcs)
336 HexEdit_SetFont(infoPtr, GetStockObject(SYSTEM_FONT), FALSE);
337 HexEdit_UpdateScrollbars(infoPtr);
339 return 0;
343 static inline LRESULT
344 HexEdit_Destroy (HEXEDIT_INFO *infoPtr)
346 HWND hwnd = infoPtr->hwndSelf;
347 HeapFree(GetProcessHeap(), 0, infoPtr->pData);
348 /* free info data */
349 HeapFree(GetProcessHeap(), 0, infoPtr);
350 SetWindowLongPtr(hwnd, 0, 0);
351 return 0;
355 static inline LRESULT
356 HexEdit_EraseBackground (HEXEDIT_INFO *infoPtr, HDC hdc)
358 HBRUSH hBrush, hSolidBrush = NULL;
359 RECT rc;
361 if (GetWindowLong(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
362 hBrush = hSolidBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
363 else
365 hBrush = (HBRUSH)SendMessage(GetParent(infoPtr->hwndSelf), WM_CTLCOLOREDIT,
366 (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
367 if (!hBrush)
368 hBrush = hSolidBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
371 GetClientRect (infoPtr->hwndSelf, &rc);
373 FillRect (hdc, &rc, hBrush);
375 if (hSolidBrush)
376 DeleteObject(hSolidBrush);
378 return -1;
382 static inline LRESULT
383 HexEdit_GetFont (HEXEDIT_INFO *infoPtr)
385 return (LRESULT)infoPtr->hFont;
388 static inline LRESULT
389 HexEdit_KeyDown (HEXEDIT_INFO *infoPtr, DWORD key, DWORD flags)
391 INT nInc = (infoPtr->bFocusHex) ? 1 : 2;
392 SCROLLINFO si;
394 switch (key)
396 case VK_LEFT:
397 infoPtr->nCaretPos -= nInc;
398 if (infoPtr->nCaretPos < 0)
399 infoPtr->nCaretPos = 0;
400 break;
401 case VK_RIGHT:
402 infoPtr->nCaretPos += nInc;
403 if (infoPtr->nCaretPos > infoPtr->cbData*2)
404 infoPtr->nCaretPos = infoPtr->cbData*2;
405 break;
406 case VK_UP:
407 if ((infoPtr->nCaretPos - infoPtr->nBytesPerLine*2) >= 0)
408 infoPtr->nCaretPos -= infoPtr->nBytesPerLine*2;
409 break;
410 case VK_DOWN:
411 if ((infoPtr->nCaretPos + infoPtr->nBytesPerLine*2) <= infoPtr->cbData*2)
412 infoPtr->nCaretPos += infoPtr->nBytesPerLine*2;
413 break;
414 case VK_HOME:
415 infoPtr->nCaretPos = 0;
416 break;
417 case VK_END:
418 infoPtr->nCaretPos = infoPtr->cbData*2;
419 break;
420 case VK_PRIOR: /* page up */
421 si.cbSize = sizeof(si);
422 si.fMask = SIF_PAGE;
423 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
424 if ((infoPtr->nCaretPos - (INT)si.nPage*infoPtr->nBytesPerLine*2) >= 0)
425 infoPtr->nCaretPos -= si.nPage*infoPtr->nBytesPerLine*2;
426 else
427 infoPtr->nCaretPos = 0;
428 break;
429 case VK_NEXT: /* page down */
430 si.cbSize = sizeof(si);
431 si.fMask = SIF_PAGE;
432 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
433 if ((infoPtr->nCaretPos + (INT)si.nPage*infoPtr->nBytesPerLine*2) <= infoPtr->cbData*2)
434 infoPtr->nCaretPos += si.nPage*infoPtr->nBytesPerLine*2;
435 else
436 infoPtr->nCaretPos = infoPtr->cbData*2;
437 break;
438 default:
439 return 0;
442 HexEdit_UpdateCaret(infoPtr);
443 HexEdit_EnsureVisible(infoPtr, infoPtr->nCaretPos);
445 return 0;
449 static inline LRESULT
450 HexEdit_KillFocus (HEXEDIT_INFO *infoPtr, HWND receiveFocus)
452 infoPtr->bFocus = FALSE;
453 DestroyCaret();
455 return 0;
459 static inline LRESULT
460 HexEdit_LButtonDown (HEXEDIT_INFO *infoPtr)
462 SetFocus(infoPtr->hwndSelf);
464 /* FIXME: hittest and set caret */
466 return 0;
470 static inline LRESULT HexEdit_NCCreate (HWND hwnd, LPCREATESTRUCT lpcs)
472 HEXEDIT_INFO *infoPtr;
473 SetWindowLong(hwnd, GWL_EXSTYLE,
474 lpcs->dwExStyle | WS_EX_CLIENTEDGE);
476 /* allocate memory for info structure */
477 infoPtr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXEDIT_INFO));
478 SetWindowLongPtr(hwnd, 0, (DWORD_PTR)infoPtr);
480 /* initialize info structure */
481 infoPtr->nCaretPos = 0;
482 infoPtr->hwndSelf = hwnd;
483 infoPtr->nBytesPerLine = 2;
484 infoPtr->bFocusHex = TRUE;
485 infoPtr->bInsert = TRUE;
487 return DefWindowProc(infoPtr->hwndSelf, WM_NCCREATE, 0, (LPARAM)lpcs);
490 static inline LRESULT
491 HexEdit_SetFocus (HEXEDIT_INFO *infoPtr, HWND lostFocus)
493 infoPtr->bFocus = TRUE;
495 CreateCaret(infoPtr->hwndSelf, NULL, 1, infoPtr->nHeight);
496 HexEdit_UpdateCaret(infoPtr);
497 ShowCaret(infoPtr->hwndSelf);
499 return 0;
503 static inline LRESULT
504 HexEdit_SetFont (HEXEDIT_INFO *infoPtr, HFONT hFont, BOOL redraw)
506 TEXTMETRIC tm;
507 HDC hdc;
508 HFONT hOldFont = NULL;
509 LONG i;
510 RECT rcClient;
512 infoPtr->hFont = hFont;
514 hdc = GetDC(infoPtr->hwndSelf);
515 if (infoPtr->hFont)
516 hOldFont = SelectObject(hdc, infoPtr->hFont);
518 GetTextMetrics(hdc, &tm);
519 infoPtr->nHeight = tm.tmHeight + tm.tmExternalLeading;
521 GetClientRect(infoPtr->hwndSelf, &rcClient);
523 for (i = 0; ; i++)
525 BYTE *pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, i);
526 LPTSTR lpszLine = HexEdit_GetLineText(pData, i, 0);
527 SIZE size;
528 GetTextExtentPoint32(hdc, lpszLine, lstrlen(lpszLine), &size);
529 HeapFree(GetProcessHeap(), 0, lpszLine);
530 HeapFree(GetProcessHeap(), 0, pData);
531 if (size.cx > (rcClient.right - rcClient.left))
533 infoPtr->nBytesPerLine = i - 1;
534 break;
538 if (infoPtr->hFont)
539 SelectObject(hdc, hOldFont);
540 ReleaseDC (infoPtr->hwndSelf, hdc);
542 if (redraw)
543 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
545 return 0;
548 static inline LRESULT
549 HexEdit_VScroll (HEXEDIT_INFO *infoPtr, INT action)
551 SCROLLINFO si;
553 /* get all scroll bar info */
554 si.cbSize = sizeof(si);
555 si.fMask = SIF_ALL;
556 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
558 switch (LOWORD(action))
560 case SB_TOP: /* user pressed the home key */
561 si.nPos = si.nMin;
562 break;
564 case SB_BOTTOM: /* user pressed the end key */
565 si.nPos = si.nMax;
566 break;
568 case SB_LINEUP: /* user clicked the up arrow */
569 si.nPos -= 1;
570 break;
572 case SB_LINEDOWN: /* user clicked the down arrow */
573 si.nPos += 1;
574 break;
576 case SB_PAGEUP: /* user clicked the scroll bar above the scroll thumb */
577 si.nPos -= si.nPage;
578 break;
580 case SB_PAGEDOWN: /* user clicked the scroll bar below the scroll thumb */
581 si.nPos += si.nPage;
582 break;
584 case SB_THUMBTRACK: /* user dragged the scroll thumb */
585 si.nPos = si.nTrackPos;
586 break;
588 default:
589 break;
592 /* set the position and then retrieve it to let the system handle the
593 * cases where the position is out of range */
594 si.fMask = SIF_POS;
595 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, TRUE);
596 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
598 if (si.nPos != infoPtr->nScrollPos)
600 ScrollWindow(infoPtr->hwndSelf, 0, infoPtr->nHeight * (infoPtr->nScrollPos - si.nPos), NULL, NULL);
601 infoPtr->nScrollPos = si.nPos;
602 UpdateWindow(infoPtr->hwndSelf);
604 /* need to update caret position since it depends on the scroll position */
605 HexEdit_UpdateCaret(infoPtr);
607 return 0;
611 static LRESULT WINAPI
612 HexEdit_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
614 HEXEDIT_INFO *infoPtr = (HEXEDIT_INFO *)GetWindowLongPtr (hwnd, 0);
616 if (!infoPtr && (uMsg != WM_NCCREATE))
617 return DefWindowProc(hwnd, uMsg, wParam, lParam);
619 switch (uMsg)
621 case HEM_SETDATA:
622 return HexEdit_SetData (infoPtr, (INT)wParam, (const BYTE *)lParam);
624 case HEM_GETDATA:
625 return HexEdit_GetData (infoPtr, (INT)wParam, (BYTE *)lParam);
627 case WM_CHAR:
628 return HexEdit_Char (infoPtr, (TCHAR)wParam);
630 case WM_CREATE:
631 return HexEdit_Create (infoPtr, (LPCREATESTRUCT)lParam);
633 case WM_DESTROY:
634 return HexEdit_Destroy (infoPtr);
636 case WM_ERASEBKGND:
637 return HexEdit_EraseBackground (infoPtr, (HDC)wParam);
639 case WM_GETDLGCODE:
640 return DLGC_WANTCHARS | DLGC_WANTARROWS;
642 case WM_GETFONT:
643 return HexEdit_GetFont (infoPtr);
645 case WM_KEYDOWN:
646 return HexEdit_KeyDown (infoPtr, wParam, lParam);
648 case WM_KILLFOCUS:
649 return HexEdit_KillFocus (infoPtr, (HWND)wParam);
651 case WM_LBUTTONDOWN:
652 return HexEdit_LButtonDown (infoPtr);
654 case WM_NCCREATE:
655 return HexEdit_NCCreate (hwnd, (LPCREATESTRUCT)lParam);
657 case WM_PAINT:
658 HexEdit_Paint(infoPtr);
659 return 0;
661 case WM_SETFOCUS:
662 return HexEdit_SetFocus (infoPtr, (HWND)wParam);
664 case WM_SETFONT:
665 return HexEdit_SetFont (infoPtr, (HFONT)wParam, LOWORD(lParam));
667 case WM_VSCROLL:
668 return HexEdit_VScroll (infoPtr, (INT)wParam);
670 default:
671 return DefWindowProc(hwnd, uMsg, wParam, lParam);
673 return 0;
676 void HexEdit_Register(void)
678 WNDCLASS wndClass;
680 ZeroMemory(&wndClass, sizeof(WNDCLASS));
681 wndClass.style = 0;
682 wndClass.lpfnWndProc = HexEdit_WindowProc;
683 wndClass.cbClsExtra = 0;
684 wndClass.cbWndExtra = sizeof(HEXEDIT_INFO *);
685 wndClass.hCursor = NULL;
686 wndClass.hbrBackground = NULL;
687 wndClass.lpszClassName = HEXEDIT_CLASS;
689 RegisterClass(&wndClass);