user32: Add stub for SetThreadDpiAwarenessContext.
[wine.git] / programs / regedit / hexedit.c
blobc7bdd0ae520521cd7f5087300eb30ae5793584fc
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 <stdio.h>
28 #include <string.h>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "winnls.h"
36 #include "commctrl.h"
38 #include "wine/heap.h"
39 #include "main.h"
40 #include "regproc.h"
42 /* spaces dividing hex and ASCII */
43 #define DIV_SPACES 4
45 typedef struct tagHEXEDIT_INFO
47 HWND hwndSelf;
48 HFONT hFont;
49 BOOL bFocus : 1;
50 BOOL bFocusHex : 1; /* TRUE if focus is on hex, FALSE if focus on ASCII */
51 BOOL bInsert : 1; /* insert mode if TRUE, overwrite mode if FALSE */
52 INT nHeight; /* height of text */
53 INT nCaretPos; /* caret pos in nibbles */
54 BYTE *pData;
55 INT cbData;
56 INT nBytesPerLine; /* bytes of hex to display per line of the control */
57 INT nScrollPos; /* first visible line */
58 } HEXEDIT_INFO;
60 const WCHAR szHexEditClass[] = {'H','e','x','E','d','i','t',0};
62 static inline LRESULT HexEdit_SetFont (HEXEDIT_INFO *infoPtr, HFONT hFont, BOOL redraw);
64 static inline BYTE hexchar_to_byte(WCHAR ch)
66 if (ch >= '0' && ch <= '9')
67 return ch - '0';
68 else if (ch >= 'a' && ch <= 'f')
69 return ch - 'a' + 10;
70 else if (ch >= 'A' && ch <= 'F')
71 return ch - 'A' + 10;
72 else
73 return -1;
76 static LPWSTR HexEdit_GetLineText(int offset, BYTE *pData, LONG cbData, LONG pad)
78 static const WCHAR percent_04xW[] = {'%','0','4','X',' ',' ',0};
79 static const WCHAR percent_02xW[] = {'%','0','2','X',' ',0};
81 WCHAR *lpszLine = heap_xalloc((6 + cbData * 3 + pad * 3 + DIV_SPACES + cbData + 1) * sizeof(WCHAR));
82 LONG i;
84 wsprintfW(lpszLine, percent_04xW, offset);
86 for (i = 0; i < cbData; i++)
87 wsprintfW(lpszLine + 6 + i*3, percent_02xW, pData[offset + i]);
88 for (i = 0; i < pad * 3; i++)
89 lpszLine[6 + cbData * 3 + i] = ' ';
91 for (i = 0; i < DIV_SPACES; i++)
92 lpszLine[6 + cbData * 3 + pad * 3 + i] = ' ';
94 /* attempt an ASCII representation if the characters are printable,
95 * otherwise display a '.' */
96 for (i = 0; i < cbData; i++)
98 /* (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER) */
99 if (isprint(pData[offset + i]))
100 lpszLine[6 + cbData * 3 + pad * 3 + DIV_SPACES + i] = pData[offset + i];
101 else
102 lpszLine[6 + cbData * 3 + pad * 3 + DIV_SPACES + i] = '.';
104 lpszLine[6 + cbData * 3 + pad * 3 + DIV_SPACES + cbData] = 0;
105 return lpszLine;
108 static void
109 HexEdit_Paint(HEXEDIT_INFO *infoPtr)
111 PAINTSTRUCT ps;
112 HDC hdc = BeginPaint(infoPtr->hwndSelf, &ps);
113 INT nXStart, nYStart;
114 COLORREF clrOldText;
115 HFONT hOldFont;
116 INT iMode;
117 LONG lByteOffset = infoPtr->nScrollPos * infoPtr->nBytesPerLine;
118 int i;
120 /* Make a gap from the frame */
121 nXStart = GetSystemMetrics(SM_CXBORDER);
122 nYStart = GetSystemMetrics(SM_CYBORDER);
124 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
125 clrOldText = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
126 else
127 clrOldText = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
129 iMode = SetBkMode(hdc, TRANSPARENT);
130 hOldFont = SelectObject(hdc, infoPtr->hFont);
132 for (i = lByteOffset; i < infoPtr->cbData; i += infoPtr->nBytesPerLine)
134 LPWSTR lpszLine;
135 LONG nLineLen = min(infoPtr->cbData - i, infoPtr->nBytesPerLine);
137 lpszLine = HexEdit_GetLineText(i, infoPtr->pData, nLineLen, infoPtr->nBytesPerLine - nLineLen);
139 /* FIXME: draw hex <-> ASCII mapping highlighted? */
140 TextOutW(hdc, nXStart, nYStart, lpszLine, lstrlenW(lpszLine));
142 nYStart += infoPtr->nHeight;
143 heap_free(lpszLine);
146 SelectObject(hdc, hOldFont);
147 SetBkMode(hdc, iMode);
148 SetTextColor(hdc, clrOldText);
150 EndPaint(infoPtr->hwndSelf, &ps);
153 static void
154 HexEdit_UpdateCaret(HEXEDIT_INFO *infoPtr)
156 HDC hdc;
157 HFONT hOldFont;
158 SIZE size;
159 INT nCaretBytePos = infoPtr->nCaretPos/2;
160 INT nByteLinePos = nCaretBytePos % infoPtr->nBytesPerLine;
161 INT nLine = nCaretBytePos / infoPtr->nBytesPerLine;
162 LONG nLineLen = min(infoPtr->cbData - nLine * infoPtr->nBytesPerLine, infoPtr->nBytesPerLine);
163 LPWSTR lpszLine = HexEdit_GetLineText(nLine * infoPtr->nBytesPerLine, infoPtr->pData, nLineLen, infoPtr->nBytesPerLine - nLineLen);
164 INT nCharOffset;
166 /* calculate offset of character caret is on in the line */
167 if (infoPtr->bFocusHex)
168 nCharOffset = 6 + nByteLinePos*3 + infoPtr->nCaretPos % 2;
169 else
170 nCharOffset = 6 + infoPtr->nBytesPerLine*3 + DIV_SPACES + nByteLinePos;
172 hdc = GetDC(infoPtr->hwndSelf);
173 hOldFont = SelectObject(hdc, infoPtr->hFont);
175 GetTextExtentPoint32W(hdc, lpszLine, nCharOffset, &size);
177 SelectObject(hdc, hOldFont);
178 ReleaseDC(infoPtr->hwndSelf, hdc);
180 if (!nLineLen) size.cx = 0;
182 heap_free(lpszLine);
184 SetCaretPos(
185 GetSystemMetrics(SM_CXBORDER) + size.cx,
186 GetSystemMetrics(SM_CYBORDER) + (nLine - infoPtr->nScrollPos) * infoPtr->nHeight);
189 static void
190 HexEdit_UpdateScrollbars(HEXEDIT_INFO *infoPtr)
192 RECT rcClient;
193 INT nLines = infoPtr->cbData / infoPtr->nBytesPerLine;
194 INT nVisibleLines;
195 SCROLLINFO si;
197 GetClientRect(infoPtr->hwndSelf, &rcClient);
198 InflateRect(&rcClient, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
200 nVisibleLines = (rcClient.bottom - rcClient.top) / infoPtr->nHeight;
201 si.cbSize = sizeof(si);
202 si.fMask = SIF_RANGE | SIF_PAGE;
203 si.nMin = 0;
204 si.nMax = max(nLines - nVisibleLines, nLines);
205 si.nPage = nVisibleLines;
206 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, TRUE);
209 static void
210 HexEdit_EnsureVisible(HEXEDIT_INFO *infoPtr, INT nCaretPos)
212 INT nLine = nCaretPos / (2 * infoPtr->nBytesPerLine);
213 SCROLLINFO si;
215 si.cbSize = sizeof(si);
216 si.fMask = SIF_POS | SIF_PAGE;
217 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
218 if (nLine < si.nPos)
219 si.nPos = nLine;
220 else if (nLine >= si.nPos + si.nPage)
221 si.nPos = nLine - si.nPage + 1;
222 else
223 return;
224 si.fMask = SIF_POS;
226 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, FALSE);
227 SendMessageW(infoPtr->hwndSelf, WM_VSCROLL, MAKELONG(SB_THUMBPOSITION, 0), 0);
231 static LRESULT
232 HexEdit_SetData(HEXEDIT_INFO *infoPtr, INT cbData, const BYTE *pData)
234 heap_free(infoPtr->pData);
235 infoPtr->cbData = 0;
237 infoPtr->pData = heap_xalloc(cbData);
238 memcpy(infoPtr->pData, pData, cbData);
239 infoPtr->cbData = cbData;
241 infoPtr->nCaretPos = 0;
242 HexEdit_UpdateScrollbars(infoPtr);
243 HexEdit_UpdateCaret(infoPtr);
244 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
245 return TRUE;
248 static LRESULT
249 HexEdit_GetData(HEXEDIT_INFO *infoPtr, INT cbData, BYTE *pData)
251 if (pData)
252 memcpy(pData, infoPtr->pData, min(cbData, infoPtr->cbData));
253 return infoPtr->cbData;
256 static inline LRESULT
257 HexEdit_Char (HEXEDIT_INFO *infoPtr, WCHAR ch)
259 INT nCaretBytePos = infoPtr->nCaretPos/2;
261 assert(nCaretBytePos >= 0);
263 /* backspace is special */
264 if (ch == '\b')
266 if (infoPtr->nCaretPos == 0)
267 return 0;
269 /* if at end of byte then delete the whole byte */
270 if (infoPtr->bFocusHex && (infoPtr->nCaretPos % 2 == 0))
272 memmove(infoPtr->pData + nCaretBytePos - 1,
273 infoPtr->pData + nCaretBytePos,
274 infoPtr->cbData - nCaretBytePos);
275 infoPtr->cbData--;
276 infoPtr->nCaretPos -= 2; /* backtrack two nibble */
278 else /* blank upper nibble */
280 infoPtr->pData[nCaretBytePos] &= 0x0f;
281 infoPtr->nCaretPos--; /* backtrack one nibble */
284 else
286 if (infoPtr->bFocusHex && hexchar_to_byte(ch) == (BYTE)-1)
288 MessageBeep(MB_ICONWARNING);
289 return 0;
292 if ((infoPtr->bInsert && (infoPtr->nCaretPos % 2 == 0)) || (nCaretBytePos >= infoPtr->cbData))
294 /* make room for another byte */
295 infoPtr->cbData++;
296 infoPtr->pData = heap_xrealloc(infoPtr->pData, infoPtr->cbData + 1);
298 /* move everything after caret up one byte */
299 memmove(infoPtr->pData + nCaretBytePos + 1,
300 infoPtr->pData + nCaretBytePos,
301 infoPtr->cbData - nCaretBytePos);
302 /* zero new byte */
303 infoPtr->pData[nCaretBytePos] = 0x0;
306 /* overwrite a byte */
308 assert(nCaretBytePos < infoPtr->cbData);
310 if (infoPtr->bFocusHex)
312 BYTE orig_byte = infoPtr->pData[nCaretBytePos];
313 BYTE digit = hexchar_to_byte(ch);
314 if (infoPtr->nCaretPos % 2) /* set low nibble */
315 infoPtr->pData[nCaretBytePos] = (orig_byte & 0xf0) | digit;
316 else /* set high nibble */
317 infoPtr->pData[nCaretBytePos] = (orig_byte & 0x0f) | digit << 4;
318 infoPtr->nCaretPos++; /* advance one nibble */
320 else
322 infoPtr->pData[nCaretBytePos] = (BYTE)ch;
323 infoPtr->nCaretPos += 2; /* advance two nibbles */
327 HexEdit_UpdateScrollbars(infoPtr);
328 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
329 HexEdit_UpdateCaret(infoPtr);
330 HexEdit_EnsureVisible(infoPtr, infoPtr->nCaretPos);
331 return 0;
334 static inline LRESULT
335 HexEdit_Destroy (HEXEDIT_INFO *infoPtr)
337 HWND hwnd = infoPtr->hwndSelf;
338 heap_free(infoPtr->pData);
339 /* free info data */
340 heap_free(infoPtr);
341 SetWindowLongPtrW(hwnd, 0, 0);
342 return 0;
346 static inline LRESULT
347 HexEdit_EraseBackground (HEXEDIT_INFO *infoPtr, HDC hdc)
349 HBRUSH hBrush, hSolidBrush = NULL;
350 RECT rc;
352 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
353 hBrush = hSolidBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
354 else
356 hBrush = (HBRUSH)SendMessageW(GetParent(infoPtr->hwndSelf), WM_CTLCOLOREDIT,
357 (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
358 if (!hBrush)
359 hBrush = hSolidBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
362 GetClientRect (infoPtr->hwndSelf, &rc);
364 FillRect (hdc, &rc, hBrush);
366 if (hSolidBrush)
367 DeleteObject(hSolidBrush);
369 return -1;
373 static inline LRESULT
374 HexEdit_GetFont (HEXEDIT_INFO *infoPtr)
376 return (LRESULT)infoPtr->hFont;
379 static inline LRESULT
380 HexEdit_KeyDown (HEXEDIT_INFO *infoPtr, DWORD key, DWORD flags)
382 INT nInc = (infoPtr->bFocusHex) ? 1 : 2;
383 SCROLLINFO si;
385 switch (key)
387 case VK_LEFT:
388 infoPtr->nCaretPos -= nInc;
389 if (infoPtr->nCaretPos < 0)
390 infoPtr->nCaretPos = 0;
391 break;
392 case VK_RIGHT:
393 infoPtr->nCaretPos += nInc;
394 if (infoPtr->nCaretPos > infoPtr->cbData*2)
395 infoPtr->nCaretPos = infoPtr->cbData*2;
396 break;
397 case VK_UP:
398 if ((infoPtr->nCaretPos - infoPtr->nBytesPerLine*2) >= 0)
399 infoPtr->nCaretPos -= infoPtr->nBytesPerLine*2;
400 break;
401 case VK_DOWN:
402 if ((infoPtr->nCaretPos + infoPtr->nBytesPerLine*2) <= infoPtr->cbData*2)
403 infoPtr->nCaretPos += infoPtr->nBytesPerLine*2;
404 break;
405 case VK_HOME:
406 infoPtr->nCaretPos = 0;
407 break;
408 case VK_END:
409 infoPtr->nCaretPos = infoPtr->cbData*2;
410 break;
411 case VK_PRIOR: /* page up */
412 si.cbSize = sizeof(si);
413 si.fMask = SIF_PAGE;
414 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
415 if ((infoPtr->nCaretPos - (INT)si.nPage*infoPtr->nBytesPerLine*2) >= 0)
416 infoPtr->nCaretPos -= si.nPage*infoPtr->nBytesPerLine*2;
417 else
418 infoPtr->nCaretPos = 0;
419 break;
420 case VK_NEXT: /* page down */
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) <= infoPtr->cbData*2)
425 infoPtr->nCaretPos += si.nPage*infoPtr->nBytesPerLine*2;
426 else
427 infoPtr->nCaretPos = infoPtr->cbData*2;
428 break;
429 default:
430 return 0;
433 HexEdit_UpdateCaret(infoPtr);
434 HexEdit_EnsureVisible(infoPtr, infoPtr->nCaretPos);
436 return 0;
440 static inline LRESULT
441 HexEdit_KillFocus (HEXEDIT_INFO *infoPtr, HWND receiveFocus)
443 infoPtr->bFocus = FALSE;
444 DestroyCaret();
446 return 0;
450 static inline LRESULT
451 HexEdit_LButtonDown (HEXEDIT_INFO *infoPtr)
453 SetFocus(infoPtr->hwndSelf);
455 /* FIXME: hittest and set caret */
457 return 0;
461 static inline LRESULT HexEdit_NCCreate (HWND hwnd, LPCREATESTRUCTW lpcs)
463 HEXEDIT_INFO *infoPtr;
464 SetWindowLongW(hwnd, GWL_EXSTYLE,
465 lpcs->dwExStyle | WS_EX_CLIENTEDGE);
467 /* allocate memory for info structure */
468 infoPtr = heap_xalloc(sizeof(HEXEDIT_INFO));
469 memset(infoPtr, 0, sizeof(HEXEDIT_INFO));
470 SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr);
472 /* initialize info structure */
473 infoPtr->nCaretPos = 0;
474 infoPtr->hwndSelf = hwnd;
475 infoPtr->nBytesPerLine = 2;
476 infoPtr->bFocusHex = TRUE;
477 infoPtr->bInsert = TRUE;
479 return DefWindowProcW(infoPtr->hwndSelf, WM_NCCREATE, 0, (LPARAM)lpcs);
482 static inline LRESULT
483 HexEdit_SetFocus (HEXEDIT_INFO *infoPtr, HWND lostFocus)
485 infoPtr->bFocus = TRUE;
487 CreateCaret(infoPtr->hwndSelf, NULL, 1, infoPtr->nHeight);
488 HexEdit_UpdateCaret(infoPtr);
489 ShowCaret(infoPtr->hwndSelf);
491 return 0;
495 static inline LRESULT
496 HexEdit_SetFont (HEXEDIT_INFO *infoPtr, HFONT hFont, BOOL redraw)
498 TEXTMETRICW tm;
499 HDC hdc;
500 HFONT hOldFont = NULL;
501 LONG i;
502 RECT rcClient;
504 infoPtr->hFont = hFont;
506 hdc = GetDC(infoPtr->hwndSelf);
507 if (infoPtr->hFont)
508 hOldFont = SelectObject(hdc, infoPtr->hFont);
510 GetTextMetricsW(hdc, &tm);
511 infoPtr->nHeight = tm.tmHeight + tm.tmExternalLeading;
513 GetClientRect(infoPtr->hwndSelf, &rcClient);
515 for (i = 0; ; i++)
517 BYTE *pData = heap_xalloc(i);
518 WCHAR *lpszLine;
519 SIZE size;
521 memset(pData, 0, i);
522 lpszLine = HexEdit_GetLineText(0, pData, i, 0);
523 GetTextExtentPoint32W(hdc, lpszLine, lstrlenW(lpszLine), &size);
524 heap_free(lpszLine);
525 heap_free(pData);
526 if (size.cx > (rcClient.right - rcClient.left))
528 infoPtr->nBytesPerLine = i - 1;
529 break;
533 HexEdit_UpdateScrollbars(infoPtr);
535 if (infoPtr->hFont)
536 SelectObject(hdc, hOldFont);
537 ReleaseDC (infoPtr->hwndSelf, hdc);
539 if (redraw)
540 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
542 return 0;
545 static inline LRESULT
546 HexEdit_VScroll (HEXEDIT_INFO *infoPtr, INT action)
548 SCROLLINFO si;
550 /* get all scroll bar info */
551 si.cbSize = sizeof(si);
552 si.fMask = SIF_ALL;
553 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
555 switch (LOWORD(action))
557 case SB_TOP: /* user pressed the home key */
558 si.nPos = si.nMin;
559 break;
561 case SB_BOTTOM: /* user pressed the end key */
562 si.nPos = si.nMax;
563 break;
565 case SB_LINEUP: /* user clicked the up arrow */
566 si.nPos -= 1;
567 break;
569 case SB_LINEDOWN: /* user clicked the down arrow */
570 si.nPos += 1;
571 break;
573 case SB_PAGEUP: /* user clicked the scroll bar above the scroll thumb */
574 si.nPos -= si.nPage;
575 break;
577 case SB_PAGEDOWN: /* user clicked the scroll bar below the scroll thumb */
578 si.nPos += si.nPage;
579 break;
581 case SB_THUMBTRACK: /* user dragged the scroll thumb */
582 si.nPos = si.nTrackPos;
583 break;
585 default:
586 break;
589 /* set the position and then retrieve it to let the system handle the
590 * cases where the position is out of range */
591 si.fMask = SIF_POS;
592 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, TRUE);
593 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
595 if (si.nPos != infoPtr->nScrollPos)
597 ScrollWindow(infoPtr->hwndSelf, 0, infoPtr->nHeight * (infoPtr->nScrollPos - si.nPos), NULL, NULL);
598 infoPtr->nScrollPos = si.nPos;
599 UpdateWindow(infoPtr->hwndSelf);
601 /* need to update caret position since it depends on the scroll position */
602 HexEdit_UpdateCaret(infoPtr);
604 return 0;
608 static LRESULT WINAPI
609 HexEdit_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
611 HEXEDIT_INFO *infoPtr = (HEXEDIT_INFO *)GetWindowLongPtrW(hwnd, 0);
613 if (!infoPtr && (uMsg != WM_NCCREATE))
614 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
616 switch (uMsg)
618 case HEM_SETDATA:
619 return HexEdit_SetData (infoPtr, (INT)wParam, (const BYTE *)lParam);
621 case HEM_GETDATA:
622 return HexEdit_GetData (infoPtr, (INT)wParam, (BYTE *)lParam);
624 case WM_CHAR:
625 return HexEdit_Char (infoPtr, (WCHAR)wParam);
627 case WM_DESTROY:
628 return HexEdit_Destroy (infoPtr);
630 case WM_ERASEBKGND:
631 return HexEdit_EraseBackground (infoPtr, (HDC)wParam);
633 case WM_GETDLGCODE:
634 return DLGC_WANTCHARS | DLGC_WANTARROWS;
636 case WM_GETFONT:
637 return HexEdit_GetFont (infoPtr);
639 case WM_KEYDOWN:
640 return HexEdit_KeyDown (infoPtr, wParam, lParam);
642 case WM_KILLFOCUS:
643 return HexEdit_KillFocus (infoPtr, (HWND)wParam);
645 case WM_LBUTTONDOWN:
646 return HexEdit_LButtonDown (infoPtr);
648 case WM_NCCREATE:
649 return HexEdit_NCCreate (hwnd, (LPCREATESTRUCTW)lParam);
651 case WM_PAINT:
652 HexEdit_Paint(infoPtr);
653 return 0;
655 case WM_SETFOCUS:
656 return HexEdit_SetFocus (infoPtr, (HWND)wParam);
658 case WM_SETFONT:
659 return HexEdit_SetFont (infoPtr, (HFONT)wParam, LOWORD(lParam));
661 case WM_VSCROLL:
662 return HexEdit_VScroll (infoPtr, (INT)wParam);
664 default:
665 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
667 return 0;
670 void HexEdit_Register(void)
672 WNDCLASSW wndClass;
674 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
675 wndClass.style = 0;
676 wndClass.lpfnWndProc = HexEdit_WindowProc;
677 wndClass.cbClsExtra = 0;
678 wndClass.cbWndExtra = sizeof(HEXEDIT_INFO *);
679 wndClass.hCursor = NULL;
680 wndClass.hbrBackground = NULL;
681 wndClass.lpszClassName = szHexEditClass;
683 RegisterClassW(&wndClass);