├── .gitattributes
├── .gitignore
├── HexEdit.sln
├── HexEdit
├── HexEdit.cpp
├── HexEdit.h
├── HexEdit.ico
├── HexEdit.rc
├── HexEdit.vcxproj
├── HexEdit.vcxproj.filters
├── HexView.cpp
├── HexView.h
├── Resource.h
├── Version.rc
├── Version.txt
├── small.ico
├── stdafx.cpp
├── stdafx.h
└── targetver.h
├── LICENSE.txt
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # Roslyn cache directories
20 | *.ide/
21 |
22 | # MSTest test Results
23 | [Tt]est[Rr]esult*/
24 | [Bb]uild[Ll]og.*
25 |
26 | #NUNIT
27 | *.VisualState.xml
28 | TestResult.xml
29 |
30 | # Build Results of an ATL Project
31 | [Dd]ebugPS/
32 | [Rr]eleasePS/
33 | dlldata.c
34 |
35 | *_i.c
36 | *_p.c
37 | *_i.h
38 | *.ilk
39 | *.meta
40 | *.obj
41 | *.pch
42 | *.pdb
43 | *.pgc
44 | *.pgd
45 | *.rsp
46 | *.sbr
47 | *.tlb
48 | *.tli
49 | *.tlh
50 | *.tmp
51 | *.tmp_proj
52 | *.log
53 | *.vspscc
54 | *.vssscc
55 | .builds
56 | *.pidb
57 | *.svclog
58 | *.scc
59 |
60 | # Chutzpah Test files
61 | _Chutzpah*
62 |
63 | # Visual C++ cache files
64 | ipch/
65 | *.aps
66 | *.ncb
67 | *.opensdf
68 | *.sdf
69 | *.cachefile
70 |
71 | # Visual Studio profiler
72 | *.psess
73 | *.vsp
74 | *.vspx
75 |
76 | # TFS 2012 Local Workspace
77 | $tf/
78 |
79 | # Guidance Automation Toolkit
80 | *.gpState
81 |
82 | # ReSharper is a .NET coding add-in
83 | _ReSharper*/
84 | *.[Rr]e[Ss]harper
85 | *.DotSettings.user
86 |
87 | # JustCode is a .NET coding addin-in
88 | .JustCode
89 |
90 | # TeamCity is a build add-in
91 | _TeamCity*
92 |
93 | # DotCover is a Code Coverage Tool
94 | *.dotCover
95 |
96 | # NCrunch
97 | _NCrunch_*
98 | .*crunch*.local.xml
99 |
100 | # MightyMoose
101 | *.mm.*
102 | AutoTest.Net/
103 |
104 | # Web workbench (sass)
105 | .sass-cache/
106 |
107 | # Installshield output folder
108 | [Ee]xpress/
109 |
110 | # DocProject is a documentation generator add-in
111 | DocProject/buildhelp/
112 | DocProject/Help/*.HxT
113 | DocProject/Help/*.HxC
114 | DocProject/Help/*.hhc
115 | DocProject/Help/*.hhk
116 | DocProject/Help/*.hhp
117 | DocProject/Help/Html2
118 | DocProject/Help/html
119 |
120 | # Click-Once directory
121 | publish/
122 |
123 | # Publish Web Output
124 | *.[Pp]ublish.xml
125 | *.azurePubxml
126 | ## TODO: Comment the next line if you want to checkin your
127 | ## web deploy settings but do note that will include unencrypted
128 | ## passwords
129 | #*.pubxml
130 |
131 | # NuGet Packages Directory
132 | packages/*
133 | ## TODO: If the tool you use requires repositories.config
134 | ## uncomment the next line
135 | #!packages/repositories.config
136 |
137 | # Enable "build/" folder in the NuGet Packages folder since
138 | # NuGet packages use it for MSBuild targets.
139 | # This line needs to be after the ignore of the build folder
140 | # (and the packages folder if the line above has been uncommented)
141 | !packages/build/
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
186 | # LightSwitch generated files
187 | GeneratedArtifacts/
188 | _Pvt_Extensions/
189 | ModelManifest.xml
--------------------------------------------------------------------------------
/HexEdit.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HexEdit", "HexEdit\HexEdit.vcxproj", "{8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Debug|x64 = Debug|x64
10 | Release|Win32 = Release|Win32
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Debug|Win32.Build.0 = Debug|Win32
16 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Debug|x64.ActiveCfg = Debug|x64
17 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Debug|x64.Build.0 = Debug|x64
18 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Release|Win32.ActiveCfg = Release|Win32
19 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Release|Win32.Build.0 = Release|Win32
20 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Release|x64.ActiveCfg = Release|x64
21 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}.Release|x64.Build.0 = Release|x64
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/HexEdit/HexEdit.cpp:
--------------------------------------------------------------------------------
1 | /*++
2 |
3 | Copyright (c) Andrey Bazhan
4 |
5 | --*/
6 |
7 | #include "stdafx.h"
8 | #include "HexEdit.h"
9 | #include "HexView.h"
10 |
11 | #define APPNAME _T("HexEdit")
12 | #define WEBSITE _T("www.andreybazhan.com")
13 | #define OPTIONS_KEY _T("Software\\Andrey Bazhan\\") APPNAME
14 | #define MAINWINDOW_VALUE _T("MainWindow")
15 |
16 | HWND hMain;
17 | HWND hHexView;
18 |
19 | OPTIONS Options;
20 |
21 | HANDLE hFile;
22 | HANDLE hFileMap;
23 | ULONG_PTR FileBase;
24 | LARGE_INTEGER FileSize;
25 |
26 | TCHAR FilePath[MAX_PATH];
27 |
28 |
29 | VOID
30 | SetWindowTitleText(
31 | _In_z_ PCTSTR Text
32 | )
33 | {
34 | TCHAR Title[MAX_PATH * 2];
35 |
36 | StringCchPrintf(Title,
37 | _countof(Title),
38 | _T("%s %s"),
39 | APPNAME,
40 | Text);
41 |
42 | SetWindowText(hMain, Title);
43 | }
44 |
45 | VOID
46 | FileClose(
47 | VOID
48 | )
49 | {
50 | if (FileBase && hFileMap && hFile) {
51 |
52 | SendMessage(hHexView, HVM_SETITEMCOUNT, 0, 0);
53 |
54 | UnmapViewOfFile((LPCVOID)FileBase);
55 | FileBase = NULL;
56 |
57 | CloseHandle(hFileMap);
58 | hFileMap = 0;
59 |
60 | CloseHandle(hFile);
61 | hFile = 0;
62 |
63 | SetWindowText(hMain, APPNAME);
64 |
65 | SetFocus(hMain);
66 | }
67 | }
68 |
69 | VOID
70 | FileOpen(
71 | VOID
72 | )
73 | {
74 | FileClose();
75 |
76 | hFile = CreateFile(FilePath,
77 | GENERIC_READ,
78 | FILE_SHARE_READ,
79 | 0,
80 | OPEN_EXISTING,
81 | FILE_ATTRIBUTE_NORMAL,
82 | 0);
83 |
84 | if (INVALID_HANDLE_VALUE != hFile) {
85 |
86 | GetFileSizeEx(hFile, &FileSize);
87 |
88 | hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
89 |
90 | if (hFileMap) {
91 |
92 | FileBase = (ULONG_PTR)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
93 |
94 | if (FileBase) {
95 |
96 | DWORD Style = 0;
97 |
98 | Style |= FileSize.HighPart ? HVS_ADDRESS64 : 0;
99 | Style |= HVS_READONLY;
100 |
101 | SendMessage(hHexView, HVM_SETEXTENDEDSTYLE, 0, Style);
102 | SendMessage(hHexView, HVM_SETITEMCOUNT, 0, (LPARAM)FileSize.LowPart);
103 |
104 | SetWindowTitleText(FilePath);
105 | }
106 | else {
107 |
108 | CloseHandle(hFileMap);
109 | CloseHandle(hFile);
110 | }
111 | }
112 | else {
113 |
114 | CloseHandle(hFile);
115 | }
116 | }
117 | }
118 |
119 | VOID
120 | GetSettings(
121 | VOID
122 | )
123 | {
124 | HKEY hKey;
125 | DWORD cbData;
126 |
127 | //
128 | // Set default options
129 | //
130 |
131 | ZeroMemory(&Options, sizeof(OPTIONS));
132 |
133 | Options.WindowPlacement.rcNormalPosition.left = CW_USEDEFAULT;
134 | Options.WindowPlacement.rcNormalPosition.top = CW_USEDEFAULT;
135 | Options.WindowPlacement.rcNormalPosition.right = CW_USEDEFAULT;
136 | Options.WindowPlacement.rcNormalPosition.bottom = CW_USEDEFAULT;
137 | Options.WindowPlacement.showCmd = SW_SHOWNORMAL;
138 |
139 | //
140 | // Get options
141 | //
142 |
143 | if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, OPTIONS_KEY, 0, KEY_READ, &hKey)) {
144 |
145 | cbData = sizeof(Options.WindowPlacement);
146 |
147 | RegQueryValueEx(hKey, MAINWINDOW_VALUE, NULL, NULL, (LPBYTE)&Options.WindowPlacement, &cbData);
148 |
149 | RegCloseKey(hKey);
150 | }
151 | }
152 |
153 | VOID
154 | SaveSettings(
155 | VOID
156 | )
157 | {
158 | HKEY hKey;
159 |
160 | Options.WindowPlacement.length = sizeof(WINDOWPLACEMENT);
161 |
162 | GetWindowPlacement(hMain, &Options.WindowPlacement);
163 |
164 | Options.WindowPlacement.rcNormalPosition.right = Options.WindowPlacement.rcNormalPosition.right - Options.WindowPlacement.rcNormalPosition.left;
165 | Options.WindowPlacement.rcNormalPosition.bottom = Options.WindowPlacement.rcNormalPosition.bottom - Options.WindowPlacement.rcNormalPosition.top;
166 |
167 | if (Options.WindowPlacement.showCmd == SW_SHOWMINIMIZED) {
168 |
169 | Options.WindowPlacement.showCmd = SW_SHOWNORMAL;
170 | }
171 |
172 | //
173 | // Save options
174 | //
175 |
176 | if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, OPTIONS_KEY, &hKey)) {
177 |
178 | RegSetValueEx(hKey, MAINWINDOW_VALUE, 0, REG_BINARY, (LPBYTE)&Options.WindowPlacement, sizeof(Options.WindowPlacement));
179 |
180 | RegCloseKey(hKey);
181 | }
182 | }
183 |
184 | INT_PTR
185 | CALLBACK
186 | AboutProc(
187 | _In_ HWND hDlg,
188 | _In_ UINT message,
189 | _In_ WPARAM wParam,
190 | _In_ LPARAM lParam
191 | )
192 | {
193 | switch (message) {
194 |
195 | case WM_INITDIALOG:
196 | {
197 | TCHAR FileName[MAX_PATH];
198 | TCHAR Text[MAX_PATH] = APPNAME _T(" ");
199 | DWORD Handle;
200 | PVOID Block = NULL;
201 | DWORD BlockSize;
202 | PVOID String = NULL;
203 | UINT Length;
204 |
205 | SetWindowText(hDlg, _T("About ") APPNAME);
206 |
207 | if (GetModuleFileName(NULL, FileName, _countof(FileName))) {
208 |
209 | BlockSize = GetFileVersionInfoSize(FileName, &Handle);
210 |
211 | if (BlockSize) {
212 |
213 | Block = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BlockSize);
214 |
215 | if (Block) {
216 |
217 | GetFileVersionInfo(FileName, 0, BlockSize, Block);
218 |
219 | if (VerQueryValue(Block,
220 | _T("\\StringFileInfo\\040904b0\\FileVersion"),
221 | &String,
222 | &Length)) {
223 |
224 | _tcsncpy_s(&Text[_tcslen(Text)], _countof(Text) - _tcslen(Text), (PCTSTR)String, Length);
225 |
226 | SendMessage(GetDlgItem(hDlg, IDC_VERSION), WM_SETTEXT, 0, (LPARAM)Text);
227 | }
228 |
229 | if (VerQueryValue(Block,
230 | _T("\\StringFileInfo\\040904b0\\LegalCopyright"),
231 | &String,
232 | &Length)) {
233 |
234 | _tcsncpy_s(Text, _countof(Text), (PCTSTR)String, Length);
235 |
236 | SendMessage(GetDlgItem(hDlg, IDC_COPYRIGHT), WM_SETTEXT, 0, (LPARAM)Text);
237 | }
238 |
239 | HeapFree(GetProcessHeap(), 0, Block);
240 | }
241 | }
242 | }
243 |
244 | SendMessage(GetDlgItem(hDlg, IDC_SYSLINK), WM_SETTEXT, 0, (LPARAM)_T("") WEBSITE _T(""));
245 |
246 | return TRUE;
247 | }
248 | case WM_NOTIFY:
249 | {
250 | LPNMHDR NmHdr = (LPNMHDR)lParam;
251 |
252 | if (NmHdr->hwndFrom == GetDlgItem(hDlg, IDC_SYSLINK)) {
253 |
254 | if (NmHdr->code == NM_CLICK) {
255 |
256 | ShellExecute(hDlg, _T("open"), WEBSITE, NULL, NULL, SW_SHOWNORMAL);
257 | }
258 | }
259 |
260 | break;
261 | }
262 | case WM_COMMAND:
263 | {
264 | switch (LOWORD(wParam)) {
265 |
266 | case IDOK:
267 |
268 | EndDialog(hDlg, 0);
269 | return TRUE;
270 | }
271 |
272 | break;
273 | }
274 | case WM_CLOSE:
275 |
276 | EndDialog(hDlg, 0);
277 | return TRUE;
278 | }
279 |
280 | return FALSE;
281 | }
282 |
283 | LRESULT
284 | CALLBACK
285 | WndProc(
286 | _In_ HWND hWnd,
287 | _In_ UINT message,
288 | _In_ WPARAM wParam,
289 | _In_ LPARAM lParam
290 | )
291 | {
292 | RECT rc;
293 |
294 | switch (message) {
295 |
296 | case WM_CREATE:
297 | {
298 | RegisterClassHexView();
299 |
300 | hHexView = CreateHexView(hWnd);
301 |
302 | break;
303 | }
304 | case WM_NOTIFY:
305 | {
306 | LPNMHDR NmHdr = (LPNMHDR)lParam;
307 |
308 | if (NmHdr->hwndFrom == hHexView) {
309 |
310 | if (NmHdr->code == HVN_GETDISPINFO) {
311 |
312 | PNMHVDISPINFO DispInfo = (PNMHVDISPINFO)lParam;
313 |
314 | if (DispInfo->Item.Mask & HVIF_ADDRESS) {
315 |
316 | DispInfo->Item.Address = DispInfo->Item.NumberOfItem;
317 | }
318 | else if (DispInfo->Item.Mask & HVIF_BYTE) {
319 |
320 | PBYTE Base = (PBYTE)(FileBase + DispInfo->Item.NumberOfItem);
321 |
322 | DispInfo->Item.Value = *Base;
323 |
324 | //
325 | // Set state of the item.
326 | //
327 |
328 | if (DispInfo->Item.NumberOfItem >= 0 && DispInfo->Item.NumberOfItem <= 255) {
329 |
330 | DispInfo->Item.State = HVIS_MODIFIED;
331 | }
332 | }
333 | }
334 | else if (NmHdr->code == HVN_ITEMCHANGING) {
335 |
336 | PNMHEXVIEW HexView = (PNMHEXVIEW)lParam;
337 |
338 | PBYTE Base = (PBYTE)(FileBase + HexView->Item.NumberOfItem);
339 |
340 | *Base = HexView->Item.Value;
341 | }
342 | }
343 |
344 | break;
345 | }
346 | case WM_SIZE:
347 | {
348 | GetClientRect(hWnd, &rc);
349 |
350 | MoveWindow(hHexView,
351 | rc.left,
352 | rc.top,
353 | rc.right - rc.left,
354 | rc.bottom - rc.top,
355 | TRUE);
356 | break;
357 | }
358 | case WM_COMMAND:
359 | {
360 | switch (LOWORD(wParam)) {
361 |
362 | case IDM_FILE_OPEN:
363 | {
364 | OPENFILENAME ofn = {0};
365 |
366 | ofn.lStructSize = sizeof(OPENFILENAME);
367 | ofn.hwndOwner = hWnd;
368 | ofn.hInstance = GetModuleHandle(NULL);
369 | ofn.lpstrFilter = _T("All Files(*.*)\0*.*\0Executable Files(*.exe)\0*.exe\0Dynamic Link Library(*.dll)\0*.dll\0System Files(*.sys)\0*.sys\0\0");
370 | ofn.lpstrFile = FilePath;
371 | ofn.nMaxFile = _countof(FilePath);
372 | ofn.lpstrTitle = _T("Open File");
373 | ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
374 |
375 | if (GetOpenFileName(&ofn)) {
376 |
377 | FileOpen();
378 | }
379 |
380 | break;
381 | }
382 | case IDM_FILE_CLOSE:
383 |
384 | FileClose();
385 | break;
386 |
387 | case IDM_ABOUT:
388 |
389 | DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc);
390 | break;
391 |
392 | case IDM_EXIT:
393 |
394 | SendMessage(hWnd, WM_CLOSE, 0, 0);
395 | break;
396 |
397 | default:
398 |
399 | return DefWindowProc(hWnd, message, wParam, lParam);
400 | break;
401 | }
402 |
403 | break;
404 | }
405 | case WM_DROPFILES:
406 | {
407 | if (DragQueryFile((HDROP)wParam, 0, FilePath, _countof(FilePath))) {
408 |
409 | FileOpen();
410 | }
411 |
412 | break;
413 | }
414 | case WM_SETFOCUS:
415 |
416 | SetFocus(hHexView);
417 | break;
418 |
419 | case WM_CLOSE:
420 |
421 | FileClose();
422 |
423 | SaveSettings();
424 |
425 | DestroyWindow(hWnd);
426 | break;
427 |
428 | case WM_DESTROY:
429 |
430 | PostQuitMessage(0);
431 | break;
432 |
433 | default:
434 |
435 | return DefWindowProc(hWnd, message, wParam, lParam);
436 | break;
437 | }
438 |
439 | return 0;
440 | }
441 |
442 | int
443 | APIENTRY
444 | _tWinMain(
445 | _In_ HINSTANCE hInstance,
446 | _In_opt_ HINSTANCE hPrevInstance,
447 | _In_ LPTSTR lpCmdLine,
448 | _In_ int nCmdShow
449 | )
450 | {
451 | MSG msg;
452 | WNDCLASSEX wcex = {0};
453 | HACCEL hAccel;
454 |
455 | UNREFERENCED_PARAMETER(hPrevInstance);
456 | UNREFERENCED_PARAMETER(lpCmdLine);
457 | UNREFERENCED_PARAMETER(nCmdShow);
458 |
459 | wcex.cbSize = sizeof(WNDCLASSEX);
460 | wcex.style = 0;
461 | wcex.lpfnWndProc = WndProc;
462 | wcex.cbClsExtra = 0;
463 | wcex.cbWndExtra = 0;
464 | wcex.hInstance = hInstance;
465 | wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSAPPLICATION));
466 | wcex.hCursor = 0;
467 | wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
468 | wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINDOWSAPPLICATION);
469 | wcex.lpszClassName = APPNAME;
470 | wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSAPPLICATION));
471 |
472 | if (!RegisterClassEx(&wcex)) {
473 |
474 | MessageBox(0, _T("RegisterClassEx failed!"), APPNAME, MB_ICONERROR);
475 | return 0;
476 | }
477 |
478 | GetSettings();
479 |
480 | hMain = CreateWindowEx(WS_EX_ACCEPTFILES,
481 | APPNAME,
482 | APPNAME,
483 | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
484 | Options.WindowPlacement.rcNormalPosition.left,
485 | Options.WindowPlacement.rcNormalPosition.top,
486 | Options.WindowPlacement.rcNormalPosition.right,
487 | Options.WindowPlacement.rcNormalPosition.bottom,
488 | 0,
489 | 0,
490 | hInstance,
491 | NULL);
492 |
493 | if (!hMain) {
494 |
495 | MessageBox(0, _T("CreateWindowEx failed!"), APPNAME, MB_ICONERROR);
496 | return 0;
497 | }
498 |
499 | ShowWindow(hMain, Options.WindowPlacement.showCmd);
500 | UpdateWindow(hMain);
501 |
502 | hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSAPPLICATION));
503 |
504 | while (GetMessage(&msg, NULL, 0, 0) > 0) {
505 |
506 | if (!TranslateAccelerator(hMain, hAccel, &msg)) {
507 |
508 | TranslateMessage(&msg);
509 | DispatchMessage(&msg);
510 | }
511 | }
512 |
513 | return (int)msg.wParam;
514 | }
--------------------------------------------------------------------------------
/HexEdit/HexEdit.h:
--------------------------------------------------------------------------------
1 | /*++
2 |
3 | Copyright (c) Andrey Bazhan
4 |
5 | --*/
6 |
7 | #pragma once
8 |
9 | #include "resource.h"
10 |
11 |
12 | typedef struct _OPTIONS {
13 | WINDOWPLACEMENT WindowPlacement;
14 | } OPTIONS;
15 |
--------------------------------------------------------------------------------
/HexEdit/HexEdit.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreyBazhan/HexEdit/5346c62adb467437429385f667e35d0198a01d44/HexEdit/HexEdit.ico
--------------------------------------------------------------------------------
/HexEdit/HexEdit.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreyBazhan/HexEdit/5346c62adb467437429385f667e35d0198a01d44/HexEdit/HexEdit.rc
--------------------------------------------------------------------------------
/HexEdit/HexEdit.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {8ACB9E7C-C317-4FD8-BC9E-F650DEE333D4}
23 | Win32Proj
24 | HexEdit
25 |
26 |
27 |
28 | Application
29 | true
30 | v120
31 | Unicode
32 |
33 |
34 | Application
35 | true
36 | v120
37 | Unicode
38 |
39 |
40 | Application
41 | false
42 | v120
43 | true
44 | Unicode
45 |
46 |
47 | Application
48 | false
49 | v120
50 | true
51 | Unicode
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 | AllRules.ruleset
72 | false
73 |
74 |
75 | true
76 | AllRules.ruleset
77 | false
78 |
79 |
80 | false
81 | AllRules.ruleset
82 | false
83 |
84 |
85 | false
86 | AllRules.ruleset
87 | false
88 |
89 |
90 |
91 | Use
92 | Level4
93 | Disabled
94 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
95 | true
96 | true
97 | false
98 |
99 |
100 | Windows
101 | true
102 | Version.lib %(AdditionalOptions)
103 | type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'
104 |
105 |
106 |
107 |
108 | Use
109 | Level4
110 | Disabled
111 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
112 | true
113 | true
114 | false
115 |
116 |
117 | Windows
118 | true
119 | Version.lib %(AdditionalOptions)
120 | type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'
121 |
122 |
123 |
124 |
125 | Level4
126 | Use
127 | MinSpace
128 | true
129 | true
130 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
131 | true
132 | true
133 | MultiThreaded
134 | false
135 |
136 |
137 | Windows
138 | true
139 | true
140 | true
141 | Version.lib /PDBALTPATH:%_PDB% %(AdditionalOptions)
142 | type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'
143 |
144 |
145 |
146 |
147 | Level4
148 | Use
149 | MinSpace
150 | true
151 | true
152 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
153 | true
154 | true
155 | MultiThreaded
156 | false
157 |
158 |
159 | Windows
160 | true
161 | true
162 | true
163 | Version.lib /PDBALTPATH:%_PDB% %(AdditionalOptions)
164 | type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 | Create
183 | Create
184 | Create
185 | Create
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/HexEdit/HexEdit.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 |
35 |
36 | Source Files
37 |
38 |
39 | Source Files
40 |
41 |
42 | Source Files
43 |
44 |
45 |
46 |
47 | Resource Files
48 |
49 |
50 | Resource Files
51 |
52 |
53 |
54 |
55 | Resource Files
56 |
57 |
58 | Resource Files
59 |
60 |
61 |
62 |
63 | Resource Files
64 |
65 |
66 |
--------------------------------------------------------------------------------
/HexEdit/HexView.cpp:
--------------------------------------------------------------------------------
1 | /*++
2 |
3 | Copyright (c) Andrey Bazhan
4 |
5 | --*/
6 |
7 | #include "stdafx.h"
8 | #include "HexView.h"
9 |
10 |
11 | #define IDT_TIMER 1
12 |
13 | #define NUMBEROF_CHARS_IN_FIRST_COLUMN_64BIT 1 + 16 + 2
14 | #define NUMBEROF_CHARS_IN_FIRST_COLUMN_32BIT 1 + 8 + 2
15 | #define NUMBEROF_CHARS_IN_SECOND_COLUMN 16 * 3 + 1
16 | #define NUMBEROF_CHARS_IN_THIRD_COLUMN 16
17 |
18 |
19 | VOID
20 | HexView_SendNotify(
21 | _In_ HWND hWnd,
22 | _In_ UINT Code,
23 | _In_ LPNMHDR NmHdr
24 | )
25 | {
26 | NmHdr->hwndFrom = hWnd;
27 | NmHdr->code = Code;
28 |
29 | SendMessage(GetParent(hWnd), WM_NOTIFY, 0, (LPARAM)NmHdr);
30 | }
31 |
32 | VOID
33 | HexView_DrawLine(
34 | _In_ HWND hWnd,
35 | _In_ HDC hdcMem,
36 | _In_ PHEXVIEW HexView,
37 | _In_ int NumberOfLine
38 | )
39 | {
40 | RECT rc = {0};
41 |
42 | //
43 | // Clean hdcMem
44 | //
45 |
46 | rc.right = HexView->WidthView;
47 | rc.bottom = HexView->HeightChar;
48 | ExtTextOut(hdcMem, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
49 |
50 | if ((HexView->VscrollPos + NumberOfLine) < HexView->TotalLines) {
51 |
52 | NMHVDISPINFO DispInfo = {0};
53 | TCHAR Buffer[32];
54 | int ShiftPosX;
55 | int Position1, Position2;
56 | SIZE_T SelectionStart, SelectionEnd;
57 | SIZE_T i, NumberOfItem;
58 | COLORREF clrBk;
59 |
60 | //
61 | // Address column
62 | //
63 |
64 | NumberOfItem = (HexView->VscrollPos + NumberOfLine) * 16;
65 |
66 | DispInfo.Item.Mask = HVIF_ADDRESS;
67 | DispInfo.Item.NumberOfItem = NumberOfItem;
68 | HexView_SendNotify(hWnd, HVN_GETDISPINFO, (LPNMHDR)&DispInfo);
69 |
70 | SetTextColor(hdcMem, HexView->clrText);
71 |
72 | StringCchPrintf(Buffer, _countof(Buffer), (HexView->ExStyle & HVS_ADDRESS64) ? _T("%016I64X") : _T("%08X"), DispInfo.Item.Address);
73 |
74 | ShiftPosX = -(HexView->WidthChar * HexView->HscrollPos) + HexView->WidthChar;
75 | TextOut(hdcMem, ShiftPosX, 0, (PCTSTR)Buffer, (int)_tcslen(Buffer));
76 |
77 | //
78 | // DATA and VALUE columns
79 | //
80 |
81 | Position1 = HexView->Line1;
82 | Position2 = HexView->Line2;
83 |
84 | SelectionStart = min(HexView->SelectionStart, HexView->SelectionEnd);
85 | SelectionEnd = max(HexView->SelectionStart, HexView->SelectionEnd);
86 |
87 | for (i = NumberOfItem; i <= NumberOfItem + 15 && i < HexView->TotalItems; i++) {
88 |
89 | DispInfo.Item.Mask = HVIF_BYTE;
90 | DispInfo.Item.State = 0;
91 | DispInfo.Item.NumberOfItem = i;
92 | DispInfo.Item.Address = 0;
93 | DispInfo.Item.Value = 0;
94 | HexView_SendNotify(hWnd, HVN_GETDISPINFO, (LPNMHDR)&DispInfo);
95 |
96 | if ((HexView->Flags & HVF_SELECTED) && (i >= SelectionStart && i <= SelectionEnd)) {
97 |
98 | clrBk = SetBkColor(hdcMem, HexView->clrSelectedTextBackground);
99 |
100 | if (i != SelectionEnd && i != NumberOfItem + 15) {
101 |
102 | rc.top = 0;
103 | rc.bottom = HexView->HeightView;
104 | rc.left = Position1 + HexView->WidthChar * 2;
105 | rc.right = rc.left + HexView->WidthChar;
106 |
107 | ExtTextOut(hdcMem, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
108 | }
109 | }
110 | else {
111 |
112 | clrBk = SetBkColor(hdcMem, HexView->clrTextBackground);
113 | }
114 |
115 | if (DispInfo.Item.State & HVIS_MODIFIED) {
116 |
117 | SetTextColor(hdcMem, HexView->clrModifiedText);
118 | }
119 | else {
120 |
121 | SetTextColor(hdcMem, HexView->clrText);
122 | }
123 |
124 | //
125 | // Draw a hex value
126 | //
127 |
128 | StringCchPrintf(Buffer, _countof(Buffer), _T("%02X"), DispInfo.Item.Value);
129 |
130 | TextOut(hdcMem, Position1, 0, (PCTSTR)Buffer, 2);
131 |
132 | //
133 | // Draw a char value
134 | //
135 |
136 | if (isprint(DispInfo.Item.Value)) {
137 |
138 | StringCchPrintf(Buffer, _countof(Buffer), _T("%c"), DispInfo.Item.Value);
139 | }
140 | else {
141 |
142 | _tcscpy_s(Buffer, _countof(Buffer), _T("."));
143 | }
144 |
145 | TextOut(hdcMem, Position2, 0, (PCTSTR)Buffer, 1);
146 |
147 | SetBkColor(hdcMem, clrBk);
148 |
149 | Position1 = Position1 + HexView->WidthChar * 3;
150 | Position2 = Position2 + HexView->WidthChar;
151 | }
152 | }
153 | }
154 |
155 | VOID
156 | HexView_Paint(
157 | _In_ HWND hWnd,
158 | _In_ HDC hdc,
159 | _In_ PHEXVIEW HexView
160 | )
161 | {
162 | HDC hdcMem;
163 | HBITMAP hbmMem;
164 | HANDLE hOld;
165 | HANDLE hOldFont;
166 | COLORREF clrBk;
167 | int NumberOfLine;
168 |
169 | hdcMem = CreateCompatibleDC(hdc);
170 | hbmMem = CreateCompatibleBitmap(hdc, HexView->WidthView, HexView->HeightChar);
171 |
172 | hOld = SelectObject(hdcMem, hbmMem);
173 | hOldFont = SelectObject(hdcMem, HexView->hFont);
174 |
175 | clrBk = SetBkColor(hdcMem, HexView->clrTextBackground);
176 |
177 | for (NumberOfLine = 0; NumberOfLine <= HexView->VisibleLines; NumberOfLine++) {
178 |
179 | HexView_DrawLine(hWnd, hdcMem, HexView, NumberOfLine);
180 |
181 | BitBlt(hdc, 0, HexView->HeightChar * NumberOfLine, HexView->WidthView, HexView->HeightChar, hdcMem, 0, 0, SRCCOPY);
182 | }
183 |
184 | SetBkColor(hdcMem, clrBk);
185 |
186 | SelectObject(hdcMem, hOldFont);
187 | SelectObject(hdcMem, hOld);
188 |
189 | DeleteObject(hbmMem);
190 | DeleteDC(hdcMem);
191 | }
192 |
193 | _Check_return_
194 | BOOL
195 | HexView_PinToBottom(
196 | _Inout_ PHEXVIEW HexView
197 | )
198 | {
199 | BOOL IsOk = FALSE;
200 | LONG_PTR VisibleLines;
201 | int VisibleChars;
202 |
203 | VisibleLines = min(HexView->VisibleLines, HexView->TotalLines);
204 | VisibleChars = min(HexView->VisibleChars, HexView->LongestLine);
205 |
206 | if (HexView->VscrollPos + VisibleLines > HexView->TotalLines) {
207 |
208 | HexView->VscrollPos = HexView->TotalLines - VisibleLines;
209 |
210 | IsOk = TRUE;
211 | }
212 |
213 | if (HexView->HscrollPos + VisibleChars > HexView->LongestLine) {
214 |
215 | int HscrollPos = HexView->LongestLine - VisibleChars;
216 |
217 | HexView->Line1 -= HexView->WidthChar * (HscrollPos - HexView->HscrollPos);
218 | HexView->Line2 -= HexView->WidthChar * (HscrollPos - HexView->HscrollPos);
219 |
220 | HexView->HscrollPos = HscrollPos;
221 |
222 | IsOk = TRUE;
223 | }
224 |
225 | return IsOk;
226 | }
227 |
228 | _Check_return_
229 | LONG_PTR
230 | HexView_GetTrackPos(
231 | _In_ HWND hWnd,
232 | _In_ PHEXVIEW HexView,
233 | _In_ int nBar
234 | )
235 | {
236 | SCROLLINFO si = {0};
237 |
238 | si.cbSize = sizeof(SCROLLINFO);
239 | si.fMask = SIF_TRACKPOS | SIF_PAGE;
240 |
241 | GetScrollInfo(hWnd, nBar, &si);
242 |
243 | if (nBar == SB_VERT) {
244 |
245 | if (HexView->VscrollMax > MAXLONG) {
246 |
247 | if (si.nTrackPos == (int)(MAXSHORT - si.nPage + 1)) {
248 |
249 | return HexView->VscrollMax - si.nPage + 1;
250 | }
251 |
252 | return (HexView->VscrollMax / MAXSHORT) * si.nTrackPos;
253 | }
254 | }
255 |
256 | return si.nTrackPos;
257 | }
258 |
259 | VOID
260 | HexView_SetScrollInfo(
261 | _In_ HWND hWnd,
262 | _In_ PHEXVIEW HexView
263 | )
264 | {
265 | SCROLLINFO si = {0};
266 |
267 | si.cbSize = sizeof(SCROLLINFO);
268 | si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
269 |
270 | if (HexView->VscrollMax <= MAXLONG) {
271 |
272 | si.nPos = (int)HexView->VscrollPos;
273 | si.nPage = (UINT)HexView->VisibleLines;
274 | si.nMin = 0;
275 | si.nMax = (int)HexView->VscrollMax;
276 | }
277 | else {
278 |
279 | si.nPos = (int)(HexView->VscrollPos / (HexView->VscrollMax / MAXSHORT));
280 | si.nPage = (UINT)HexView->VisibleLines;
281 | si.nMin = 0;
282 | si.nMax = MAXSHORT;
283 | }
284 |
285 | SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
286 |
287 | si.nPos = HexView->HscrollPos;
288 | si.nPage = (UINT)HexView->VisibleChars;
289 | si.nMin = 0;
290 | si.nMax = HexView->HscrollMax;
291 |
292 | SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
293 | }
294 |
295 | VOID
296 | HexView_SetCaret(
297 | _In_ HWND hWnd,
298 | _Inout_ PHEXVIEW HexView
299 | )
300 |
301 | /*++
302 |
303 | Note:
304 |
305 | Hiding is cumulative.
306 | If your application calls HideCaret five times in a row,
307 | it must also call ShowCaret five times before the caret is displayed.
308 | So we need IsCaretVisible in order to hide the caret only once.
309 |
310 | --*/
311 |
312 | {
313 | LONG_PTR NumberOfLine = HexView->NumberOfItem / 16;
314 | int NumberOfItemInLine = (int)(HexView->NumberOfItem % 16);
315 |
316 | if (HexView->TotalItems &&
317 | NumberOfLine >= HexView->VscrollPos &&
318 | NumberOfLine <= HexView->VscrollPos + HexView->VisibleLines)
319 | {
320 | switch (HexView->ActiveColumn) {
321 |
322 | case COLUMN_DATA:
323 |
324 | SetCaretPos(HexView->Line1 + (HexView->WidthChar * ((NumberOfItemInLine * 3) + HexView->PositionInItem)),
325 | (int)(NumberOfLine - HexView->VscrollPos) * HexView->HeightChar);
326 | break;
327 |
328 | case COLUMN_VALUE:
329 |
330 | SetCaretPos(HexView->Line2 + (HexView->WidthChar * NumberOfItemInLine),
331 | (int)(NumberOfLine - HexView->VscrollPos) * HexView->HeightChar);
332 | break;
333 | }
334 |
335 | ShowCaret(hWnd);
336 | HexView->Flags |= HVF_CARETVISIBLE;
337 | }
338 | else if (HexView->Flags & HVF_CARETVISIBLE) {
339 |
340 | HideCaret(hWnd);
341 | HexView->Flags &= ~HVF_CARETVISIBLE;
342 | }
343 | }
344 |
345 | VOID
346 | HexView_SetPositionOfColumns(
347 | _Inout_ PHEXVIEW HexView
348 | )
349 | {
350 | if (HexView->ExStyle & HVS_ADDRESS64) {
351 |
352 | HexView->Line1 = HexView->WidthChar * (NUMBEROF_CHARS_IN_FIRST_COLUMN_64BIT - HexView->HscrollPos);
353 | HexView->Line2 = HexView->WidthChar * ((NUMBEROF_CHARS_IN_FIRST_COLUMN_64BIT + NUMBEROF_CHARS_IN_SECOND_COLUMN) - HexView->HscrollPos);
354 | }
355 | else {
356 |
357 | HexView->Line1 = HexView->WidthChar * (NUMBEROF_CHARS_IN_FIRST_COLUMN_32BIT - HexView->HscrollPos);
358 | HexView->Line2 = HexView->WidthChar * ((NUMBEROF_CHARS_IN_FIRST_COLUMN_32BIT + NUMBEROF_CHARS_IN_SECOND_COLUMN) - HexView->HscrollPos);
359 | }
360 | }
361 |
362 | _Check_return_
363 | BOOL
364 | HexView_SetNumberOfItem(
365 | _Inout_ PHEXVIEW HexView,
366 | _In_ int xPos,
367 | _In_ int yPos
368 | )
369 | {
370 | LONG_PTR NumberOfLine;
371 |
372 | _ASSERTE(yPos >= 0);
373 |
374 | NumberOfLine = yPos / HexView->HeightChar;
375 |
376 | if (NumberOfLine == HexView->VisibleLines) {
377 | NumberOfLine--;
378 | }
379 |
380 | NumberOfLine += HexView->VscrollPos;
381 |
382 | if (NumberOfLine >= 0 && NumberOfLine < HexView->TotalLines) {
383 |
384 | SIZE_T NumberOfItem = NumberOfLine * 16;
385 | LONG_PTR NumberOfItemsInLine = HexView->TotalItems - NumberOfItem;
386 |
387 | if (NumberOfItemsInLine > 16) {
388 | NumberOfItemsInLine = 16;
389 | }
390 |
391 | if ((xPos > HexView->Line1 - HexView->WidthChar * 2) &&
392 | (xPos < (HexView->Line1 + ((NumberOfItemsInLine * 3) - 1) * HexView->WidthChar)))
393 | {
394 | xPos = (xPos - HexView->Line1) / HexView->WidthChar;
395 |
396 | HexView->NumberOfItem = NumberOfItem + ((xPos + 1) / 3);
397 | HexView->PositionInItem = ((xPos + 1) % 3) >> 1;
398 | HexView->ActiveColumn = COLUMN_DATA;
399 | }
400 | else if ((xPos > HexView->Line2 - HexView->WidthChar) &&
401 | (xPos < (HexView->Line2 + NumberOfItemsInLine * HexView->WidthChar)))
402 | {
403 | xPos = (xPos - HexView->Line2) / HexView->WidthChar;
404 |
405 | HexView->NumberOfItem = NumberOfItem + xPos;
406 | HexView->PositionInItem = 0;
407 | HexView->ActiveColumn = COLUMN_VALUE;
408 | }
409 |
410 | return TRUE;
411 | }
412 |
413 | return FALSE;
414 | }
415 |
416 | LRESULT
417 | CALLBACK
418 | HexViewProc(
419 | _In_ HWND hWnd,
420 | _In_ UINT message,
421 | _In_ WPARAM wParam,
422 | _In_ LPARAM lParam
423 | )
424 | {
425 | PHEXVIEW HexView;
426 |
427 | HexView = (PHEXVIEW)GetWindowLongPtr(hWnd, GWLP_USERDATA);
428 |
429 | switch (message) {
430 |
431 | case WM_CREATE:
432 | {
433 | HexView = (PHEXVIEW)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXVIEW));
434 |
435 | if (!HexView) {
436 |
437 | return -1;
438 | }
439 |
440 | SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)HexView);
441 |
442 | HexView->ActiveColumn = COLUMN_DATA;
443 |
444 | HexView->clrText = RGB(0, 0, 0);
445 | HexView->clrTextBackground = RGB(255, 255, 255);
446 | HexView->clrSelectedTextBackground = RGB(180, 220, 255);
447 | HexView->clrModifiedText = RGB(255, 0, 0);
448 |
449 | SendMessage(hWnd, WM_SETFONT, 0, 0);
450 | break;
451 | }
452 | case WM_SETFONT:
453 | {
454 | HDC hdc;
455 | TEXTMETRIC TextMetric;
456 | HANDLE hOldFont;
457 |
458 | //
459 | // Delete the font, if we created it by yourself.
460 | //
461 |
462 | if ((HexView->Flags & HVF_FONTCREATED) && HexView->hFont) {
463 |
464 | DeleteObject(HexView->hFont);
465 | HexView->Flags &= ~HVF_FONTCREATED;
466 | }
467 |
468 | HexView->hFont = (HFONT)wParam;
469 |
470 | if (!HexView->hFont) {
471 |
472 | LOGFONT LogFont;
473 |
474 | LogFont.lfHeight = -13;
475 | LogFont.lfWidth = 0;
476 | LogFont.lfEscapement = 0;
477 | LogFont.lfOrientation = 0;
478 | LogFont.lfWeight = FW_NORMAL;
479 | LogFont.lfItalic = FALSE;
480 | LogFont.lfUnderline = FALSE;
481 | LogFont.lfStrikeOut = FALSE;
482 | LogFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
483 | LogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
484 | LogFont.lfQuality = DEFAULT_QUALITY;
485 | LogFont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
486 | LogFont.lfCharSet = ANSI_CHARSET;
487 |
488 | _tcscpy_s(LogFont.lfFaceName, _countof(LogFont.lfFaceName), _T("Courier New"));
489 |
490 | HexView->hFont = CreateFontIndirect(&LogFont);
491 |
492 | if (HexView->hFont) {
493 |
494 | HexView->Flags |= HVF_FONTCREATED;
495 | }
496 | else {
497 |
498 | HexView->hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT);
499 | }
500 | }
501 |
502 | hdc = GetDC(hWnd);
503 |
504 | hOldFont = SelectObject(hdc, HexView->hFont);
505 | GetTextMetrics(hdc, &TextMetric);
506 | SelectObject(hdc, hOldFont);
507 |
508 | ReleaseDC(hWnd, hdc);
509 |
510 | HexView->WidthChar = TextMetric.tmAveCharWidth;
511 | HexView->HeightChar = TextMetric.tmHeight;
512 |
513 | HexView->VisibleLines = HexView->HeightView / HexView->HeightChar;
514 | HexView->VisibleChars = HexView->WidthView / HexView->WidthChar;
515 |
516 | if (hWnd == GetFocus()) {
517 |
518 | CreateCaret(hWnd, NULL, 1, HexView->HeightChar);
519 | }
520 |
521 | HexView_SetPositionOfColumns(HexView);
522 |
523 | HexView_SetScrollInfo(hWnd, HexView);
524 | HexView_SetCaret(hWnd, HexView);
525 |
526 | InvalidateRect(hWnd, NULL, FALSE);
527 | break;
528 | }
529 | case WM_TIMER:
530 | {
531 | switch (wParam) {
532 |
533 | case IDT_TIMER:
534 | {
535 | if (hWnd == GetCapture()) {
536 |
537 | RECT rc;
538 | POINT Point;
539 | LONG Position;
540 |
541 | GetClientRect(hWnd, &rc);
542 | GetCursorPos(&Point);
543 | ScreenToClient(hWnd, &Point);
544 |
545 | if (Point.y < rc.top) {
546 |
547 | SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, -1);
548 |
549 | Position = MAKELPARAM(Point.x, 0);
550 | SendMessage(hWnd, WM_MOUSEMOVE, 0, Position);
551 | }
552 | else if (Point.y > rc.bottom) {
553 |
554 | SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, -1);
555 |
556 | Position = MAKELPARAM(Point.x, rc.bottom - HexView->WidthChar);
557 | SendMessage(hWnd, WM_MOUSEMOVE, 0, Position);
558 | }
559 | }
560 | break;
561 | }
562 | }
563 |
564 | break;
565 | }
566 | case WM_RBUTTONDOWN:
567 | {
568 | if (HexView->TotalItems) {
569 |
570 | NMHDR NmHdr = {0};
571 |
572 | SendMessage(hWnd, WM_SETFOCUS, 0, 0);
573 |
574 | HexView_SendNotify(hWnd, NM_RCLICK, &NmHdr);
575 | }
576 | break;
577 | }
578 | case WM_LBUTTONDOWN:
579 | {
580 | int xPos = GET_X_LPARAM(lParam);
581 | int yPos = GET_Y_LPARAM(lParam);
582 |
583 | if (HexView_SetNumberOfItem(HexView, xPos, yPos)) {
584 |
585 | HexView->SelectionStart = HexView->SelectionEnd = HexView->NumberOfItem;
586 |
587 | if (HexView->Flags & HVF_SELECTED) {
588 |
589 | HexView->Flags &= ~HVF_SELECTED;
590 |
591 | InvalidateRect(hWnd, NULL, FALSE);
592 | }
593 |
594 | HexView_SetCaret(hWnd, HexView);
595 | SetFocus(hWnd);
596 |
597 | SetCapture(hWnd);
598 | SetTimer(hWnd, IDT_TIMER, USER_TIMER_MINIMUM, (TIMERPROC)NULL);
599 | }
600 |
601 | break;
602 | }
603 | case WM_LBUTTONUP:
604 | {
605 | if (hWnd == GetCapture()) {
606 |
607 | KillTimer(hWnd, IDT_TIMER);
608 | ReleaseCapture();
609 | }
610 |
611 | break;
612 | }
613 | case WM_MOUSEMOVE:
614 | {
615 | RECT rc;
616 | int xPos = GET_X_LPARAM(lParam);
617 | int yPos = GET_Y_LPARAM(lParam);
618 |
619 | GetClientRect(hWnd, &rc);
620 |
621 | if (yPos < rc.top || yPos > rc.bottom) {
622 | break;
623 | }
624 |
625 | if (hWnd == GetCapture()) {
626 |
627 | if (HexView_SetNumberOfItem(HexView, xPos, yPos)) {
628 |
629 | HexView->SelectionEnd = HexView->NumberOfItem;
630 | HexView->Flags |= HVF_SELECTED;
631 |
632 | HexView_SetCaret(hWnd, HexView);
633 |
634 | InvalidateRect(hWnd, NULL, FALSE);
635 | }
636 | }
637 |
638 | break;
639 | }
640 | case WM_CHAR:
641 | {
642 | if (HexView->TotalItems && !(HexView->ExStyle & HVS_READONLY)) {
643 |
644 | switch (HexView->ActiveColumn) {
645 |
646 | case COLUMN_DATA:
647 | {
648 | if (_istxdigit((wint_t)wParam)) {
649 |
650 | NMHVDISPINFO DispInfo = {0};
651 | NMHEXVIEW NmHexView = {0};
652 | TCHAR Buffer[4] = {0};
653 | BYTE Value;
654 |
655 | DispInfo.Item.Mask = HVIF_BYTE;
656 | DispInfo.Item.NumberOfItem = HexView->NumberOfItem;
657 | HexView_SendNotify(hWnd, HVN_GETDISPINFO, (LPNMHDR)&DispInfo);
658 |
659 | Buffer[0] = (TCHAR)wParam;
660 | Value = (BYTE)_tcstoul((PCTSTR)Buffer, 0, 16);
661 |
662 | if (HexView->PositionInItem) {
663 |
664 | DispInfo.Item.Value &= 0xf0;
665 | DispInfo.Item.Value |= Value;
666 | }
667 | else {
668 |
669 | DispInfo.Item.Value &= 0x0f;
670 | DispInfo.Item.Value |= (Value << 4);
671 | }
672 |
673 | NmHexView.Item.NumberOfItem = HexView->NumberOfItem;
674 | NmHexView.Item.Value = DispInfo.Item.Value;
675 | HexView_SendNotify(hWnd, HVN_ITEMCHANGING, (LPNMHDR)&NmHexView);
676 |
677 | SendMessage(hWnd, WM_KEYDOWN, VK_RIGHT, 0);
678 | }
679 | break;
680 | }
681 | case COLUMN_VALUE:
682 | {
683 | if (_istprint((wint_t)wParam) && wParam != VK_TAB) {
684 |
685 | NMHEXVIEW NmHexView = {0};
686 |
687 | NmHexView.Item.NumberOfItem = HexView->NumberOfItem;
688 | NmHexView.Item.Value = (BYTE)wParam;
689 | HexView_SendNotify(hWnd, HVN_ITEMCHANGING, (LPNMHDR)&NmHexView);
690 |
691 | SendMessage(hWnd, WM_KEYDOWN, VK_RIGHT, 0);
692 | }
693 | break;
694 | }
695 | }
696 | }
697 |
698 | break;
699 | }
700 | case WM_KEYDOWN:
701 | {
702 | if (HexView->TotalItems) {
703 |
704 | BOOLEAN IsCtrlKeyDown = (GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE;
705 |
706 | switch (wParam) {
707 |
708 | case VK_TAB:
709 | {
710 | switch (HexView->ActiveColumn) {
711 |
712 | case COLUMN_DATA:
713 |
714 | HexView->ActiveColumn = COLUMN_VALUE;
715 | break;
716 |
717 | case COLUMN_VALUE:
718 |
719 | HexView->ActiveColumn = COLUMN_DATA;
720 | break;
721 | }
722 |
723 | HexView->PositionInItem = 0;
724 | break;
725 | }
726 | case VK_LEFT:
727 | {
728 | if (IsCtrlKeyDown) {
729 |
730 | SendMessage(hWnd, WM_HSCROLL, SB_LINELEFT, 0);
731 | break;
732 | }
733 |
734 | switch (HexView->ActiveColumn) {
735 |
736 | case COLUMN_DATA:
737 | {
738 | switch (HexView->PositionInItem) {
739 |
740 | case 0:
741 | {
742 | if (HexView->NumberOfItem != 0) {
743 |
744 | LONG_PTR NumberOfLine;
745 |
746 | HexView->PositionInItem = 1;
747 | HexView->NumberOfItem--;
748 |
749 | NumberOfLine = HexView->NumberOfItem / 16;
750 |
751 | if (NumberOfLine == HexView->VscrollPos - 1) {
752 |
753 | SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0);
754 | }
755 | }
756 | break;
757 | }
758 | case 1:
759 | {
760 | HexView->PositionInItem = 0;
761 | break;
762 | }
763 | }
764 | break;
765 | }
766 | case COLUMN_VALUE:
767 | {
768 | if (HexView->NumberOfItem != 0) {
769 |
770 | LONG_PTR NumberOfLine;
771 |
772 | HexView->NumberOfItem--;
773 |
774 | NumberOfLine = HexView->NumberOfItem / 16;
775 |
776 | if (NumberOfLine == HexView->VscrollPos - 1) {
777 |
778 | SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0);
779 | }
780 | }
781 | break;
782 | }
783 | }
784 | break;
785 | }
786 | case VK_RIGHT:
787 | {
788 | if (IsCtrlKeyDown) {
789 |
790 | SendMessage(hWnd, WM_HSCROLL, SB_LINERIGHT, 0);
791 | break;
792 | }
793 |
794 | switch (HexView->ActiveColumn) {
795 |
796 | case COLUMN_DATA:
797 | {
798 | switch (HexView->PositionInItem) {
799 |
800 | case 0:
801 | {
802 | HexView->PositionInItem = 1;
803 | break;
804 | }
805 | case 1:
806 | {
807 | if (HexView->NumberOfItem < HexView->TotalItems - 1) {
808 |
809 | LONG_PTR NumberOfLine;
810 |
811 | HexView->PositionInItem = 0;
812 | HexView->NumberOfItem++;
813 |
814 | NumberOfLine = HexView->NumberOfItem / 16;
815 |
816 | if (NumberOfLine == HexView->VscrollPos + HexView->VisibleLines) {
817 |
818 | SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0);
819 | }
820 | }
821 | break;
822 | }
823 | }
824 | break;
825 | }
826 | case COLUMN_VALUE:
827 | {
828 | if (HexView->NumberOfItem < HexView->TotalItems - 1) {
829 |
830 | LONG_PTR NumberOfLine;
831 |
832 | HexView->NumberOfItem++;
833 |
834 | NumberOfLine = HexView->NumberOfItem / 16;
835 |
836 | if (NumberOfLine == HexView->VscrollPos + HexView->VisibleLines) {
837 |
838 | SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0);
839 | }
840 | }
841 | break;
842 | }
843 | }
844 | break;
845 | }
846 | case VK_UP:
847 | {
848 | if (IsCtrlKeyDown) {
849 |
850 | SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0);
851 | }
852 |
853 | if (HexView->NumberOfItem >= 16) {
854 |
855 | LONG_PTR NumberOfLine;
856 |
857 | HexView->NumberOfItem -= 16;
858 |
859 | NumberOfLine = HexView->NumberOfItem / 16;
860 |
861 | if (NumberOfLine == HexView->VscrollPos - 1) {
862 |
863 | SendMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0);
864 | }
865 | }
866 | break;
867 | }
868 | case VK_DOWN:
869 | {
870 | if (IsCtrlKeyDown) {
871 |
872 | SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0);
873 | }
874 |
875 | if ((HexView->NumberOfItem + 16) < HexView->TotalItems) {
876 |
877 | LONG_PTR NumberOfLine;
878 |
879 | HexView->NumberOfItem += 16;
880 |
881 | NumberOfLine = HexView->NumberOfItem / 16;
882 |
883 | if (NumberOfLine == HexView->VscrollPos + HexView->VisibleLines) {
884 |
885 | SendMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0);
886 | }
887 | }
888 | break;
889 | }
890 | case VK_PRIOR:
891 | {
892 | if ((HexView->NumberOfItem - 16 * HexView->VisibleLines) >= 0) {
893 |
894 | HexView->NumberOfItem -= 16 * HexView->VisibleLines;
895 | }
896 | else {
897 |
898 | SIZE_T NumberOfLines = HexView->NumberOfItem / 16;
899 | HexView->NumberOfItem -= 16 * NumberOfLines;
900 | }
901 |
902 | SendMessage(hWnd, WM_VSCROLL, SB_PAGEUP, 0);
903 | break;
904 | }
905 | case VK_NEXT:
906 | {
907 | if ((HexView->NumberOfItem + 16 * HexView->VisibleLines) < HexView->TotalItems) {
908 |
909 | HexView->NumberOfItem += 16 * HexView->VisibleLines;
910 | }
911 | else {
912 |
913 | SIZE_T NumberOfItems = HexView->TotalItems - HexView->NumberOfItem - 1;
914 | SIZE_T NumberOfLines = NumberOfItems / 16;
915 |
916 | HexView->NumberOfItem += 16 * NumberOfLines;
917 | }
918 |
919 | SendMessage(hWnd, WM_VSCROLL, SB_PAGEDOWN, 0);
920 | break;
921 | }
922 | case VK_HOME:
923 | {
924 | if (IsCtrlKeyDown) {
925 |
926 | HexView->NumberOfItem = 0;
927 | HexView->PositionInItem = 0;
928 |
929 | SendMessage(hWnd, WM_VSCROLL, SB_TOP, 0);
930 | }
931 | else {
932 |
933 | HexView->NumberOfItem &= ~0xf;
934 | HexView->PositionInItem = 0;
935 |
936 | if (HexView->ActiveColumn == COLUMN_DATA) {
937 |
938 | SendMessage(hWnd, WM_HSCROLL, SB_LEFT, 0);
939 | }
940 | }
941 | break;
942 | }
943 | case VK_END:
944 | {
945 | if (IsCtrlKeyDown) {
946 |
947 | HexView->NumberOfItem = HexView->TotalItems - 1;
948 | HexView->PositionInItem = 0;
949 |
950 | SendMessage(hWnd, WM_VSCROLL, SB_BOTTOM, 0);
951 | }
952 | else {
953 |
954 | HexView->NumberOfItem = (HexView->NumberOfItem & ~0xf) + 15;
955 | HexView->PositionInItem = 0;
956 |
957 | if (HexView->NumberOfItem >= HexView->TotalItems) {
958 |
959 | HexView->NumberOfItem = HexView->TotalItems - 1;
960 | }
961 |
962 | SendMessage(hWnd, WM_HSCROLL, SB_RIGHT, 0);
963 | }
964 | break;
965 | }
966 | }
967 |
968 | //
969 | // if lParam == 0 then WM_KEYDOWN came from WM_CHAR
970 | // and we don't need to select text.
971 | //
972 |
973 | if ((GetKeyState(VK_SHIFT) & 0x8000) && lParam) {
974 |
975 | if (HexView->PositionInItem || (HexView->SelectionStart != HexView->NumberOfItem)) {
976 |
977 | HexView->SelectionEnd = HexView->NumberOfItem;
978 | HexView->Flags |= HVF_SELECTED;
979 | }
980 | else {
981 |
982 | HexView->Flags &= ~HVF_SELECTED;
983 | }
984 | }
985 | else if (!IsCtrlKeyDown && !(GetKeyState(VK_APPS) & 0x8000)) {
986 |
987 | HexView->SelectionStart = HexView->SelectionEnd = HexView->NumberOfItem;
988 | HexView->Flags &= ~HVF_SELECTED;
989 | }
990 |
991 | if (!(HexView->Flags & HVF_CARETVISIBLE)) {
992 |
993 | LONG_PTR NumberOfLine = HexView->NumberOfItem / 16;
994 |
995 | if (NumberOfLine > HexView->TotalLines - HexView->VisibleLines) {
996 |
997 | HexView->VscrollPos = HexView->TotalLines - HexView->VisibleLines;
998 | }
999 | else {
1000 |
1001 | HexView->VscrollPos = NumberOfLine;
1002 | }
1003 |
1004 | HexView_SetScrollInfo(hWnd, HexView);
1005 | }
1006 |
1007 | HexView_SetCaret(hWnd, HexView);
1008 |
1009 | InvalidateRect(hWnd, NULL, FALSE);
1010 | }
1011 | break;
1012 | }
1013 | case WM_PAINT:
1014 | {
1015 | PAINTSTRUCT ps;
1016 | HDC hdc;
1017 |
1018 | hdc = BeginPaint(hWnd, &ps);
1019 | HexView_Paint(hWnd, hdc, HexView);
1020 | EndPaint(hWnd, &ps);
1021 | break;
1022 | }
1023 | case WM_SETFOCUS:
1024 | {
1025 | CreateCaret(hWnd, NULL, 1, HexView->HeightChar);
1026 |
1027 | if (HexView->Flags & HVF_CARETVISIBLE) {
1028 |
1029 | NMHDR NmHdr = {0};
1030 |
1031 | HexView_SetCaret(hWnd, HexView);
1032 | ShowCaret(hWnd);
1033 |
1034 | HexView_SendNotify(hWnd, NM_SETFOCUS, &NmHdr);
1035 | }
1036 | break;
1037 | }
1038 | case WM_KILLFOCUS:
1039 | {
1040 | if (HexView->Flags & HVF_CARETVISIBLE) {
1041 |
1042 | HideCaret(hWnd);
1043 | }
1044 |
1045 | DestroyCaret();
1046 | break;
1047 | }
1048 | case WM_VSCROLL:
1049 | {
1050 | LONG_PTR OldPos = HexView->VscrollPos;
1051 |
1052 | switch (LOWORD(wParam)) {
1053 |
1054 | case SB_TOP:
1055 |
1056 | HexView->VscrollPos = 0;
1057 | break;
1058 |
1059 | case SB_BOTTOM:
1060 |
1061 | HexView->VscrollPos = max(0, HexView->VscrollMax - HexView->VisibleLines + 1);
1062 | break;
1063 |
1064 | case SB_LINEUP:
1065 |
1066 | HexView->VscrollPos = max(0, HexView->VscrollPos - 1);
1067 | break;
1068 |
1069 | case SB_LINEDOWN:
1070 |
1071 | HexView->VscrollPos = min(HexView->VscrollPos + 1, max(0, HexView->VscrollMax - HexView->VisibleLines + 1));
1072 | break;
1073 |
1074 | case SB_PAGEUP:
1075 |
1076 | HexView->VscrollPos = max(0, HexView->VscrollPos - HexView->VisibleLines);
1077 | break;
1078 |
1079 | case SB_PAGEDOWN:
1080 |
1081 | HexView->VscrollPos = min(HexView->VscrollPos + HexView->VisibleLines, max(0, HexView->VscrollMax - HexView->VisibleLines + 1));
1082 | break;
1083 |
1084 | case SB_THUMBTRACK:
1085 |
1086 | HexView->VscrollPos = HexView_GetTrackPos(hWnd, HexView, SB_VERT);
1087 | break;
1088 | }
1089 |
1090 | if (OldPos != HexView->VscrollPos) {
1091 |
1092 | HexView_SetScrollInfo(hWnd, HexView);
1093 |
1094 | //
1095 | // If lParam == -1 then WM_VSCROLL came from WM_TIMER
1096 | // and we don't need to set the caret because it will be set in WM_MOUSEMOVE.
1097 | //
1098 |
1099 | if (-1 != lParam) {
1100 |
1101 | HexView_SetCaret(hWnd, HexView);
1102 | }
1103 |
1104 | InvalidateRect(hWnd, NULL, FALSE);
1105 | }
1106 |
1107 | break;
1108 | }
1109 | case WM_HSCROLL:
1110 | {
1111 | int OldPos = HexView->HscrollPos;
1112 |
1113 | switch (LOWORD(wParam)) {
1114 |
1115 | case SB_LEFT:
1116 |
1117 | HexView->HscrollPos = 0;
1118 | break;
1119 |
1120 | case SB_RIGHT:
1121 |
1122 | HexView->HscrollPos = max(0, HexView->HscrollMax - HexView->VisibleChars + 1);
1123 | break;
1124 |
1125 | case SB_LINELEFT:
1126 | case SB_PAGELEFT:
1127 |
1128 | HexView->HscrollPos = max(0, HexView->HscrollPos - 1);
1129 | break;
1130 |
1131 | case SB_LINERIGHT:
1132 | case SB_PAGERIGHT:
1133 |
1134 | HexView->HscrollPos = min(HexView->HscrollPos + 1, max(0, HexView->HscrollMax - HexView->VisibleChars + 1));
1135 | break;
1136 |
1137 | case SB_THUMBTRACK:
1138 |
1139 | HexView->HscrollPos = (int)HexView_GetTrackPos(hWnd, HexView, SB_HORZ);
1140 | break;
1141 | }
1142 |
1143 | if (OldPos != HexView->HscrollPos) {
1144 |
1145 | HexView_SetPositionOfColumns(HexView);
1146 |
1147 | HexView_SetScrollInfo(hWnd, HexView);
1148 | HexView_SetCaret(hWnd, HexView);
1149 |
1150 | InvalidateRect(hWnd, NULL, FALSE);
1151 | }
1152 |
1153 | break;
1154 | }
1155 | case WM_SIZE:
1156 | {
1157 | HexView->WidthView = LOWORD(lParam);
1158 | HexView->HeightView = HIWORD(lParam);
1159 |
1160 | HexView->VisibleLines = HexView->HeightView / HexView->HeightChar;
1161 | HexView->VisibleChars = HexView->WidthView / HexView->WidthChar;
1162 |
1163 | if (HexView_PinToBottom(HexView)) {
1164 |
1165 | HexView_SetCaret(hWnd, HexView);
1166 |
1167 | InvalidateRect(hWnd, NULL, FALSE);
1168 | }
1169 |
1170 | HexView_SetScrollInfo(hWnd, HexView);
1171 | break;
1172 | }
1173 | case WM_MOUSEWHEEL:
1174 | {
1175 | INT ScrollLines = 0;
1176 | SHORT Delta;
1177 |
1178 | Delta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
1179 |
1180 | SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &ScrollLines, 0);
1181 |
1182 | if (Delta > 0) {
1183 |
1184 | HexView->VscrollPos = max(0, HexView->VscrollPos - (Delta * ScrollLines));
1185 | }
1186 | else if (Delta < 0) {
1187 |
1188 | HexView->VscrollPos = min(HexView->VscrollPos + (-Delta * ScrollLines), max(0, HexView->VscrollMax - HexView->VisibleLines + 1));
1189 | }
1190 |
1191 | HexView_SetScrollInfo(hWnd, HexView);
1192 | HexView_SetCaret(hWnd, HexView);
1193 |
1194 | InvalidateRect(hWnd, NULL, FALSE);
1195 | break;
1196 | }
1197 | case HVM_SETEXTENDEDSTYLE:
1198 | {
1199 | HexView->ExStyle = (DWORD)lParam;
1200 | break;
1201 | }
1202 | case HVM_SETITEMCOUNT:
1203 | {
1204 | HexView->TotalItems = 0;
1205 | HexView->TotalLines = 0;
1206 | HexView->LongestLine = 0;
1207 |
1208 | if (lParam) {
1209 |
1210 | HexView->TotalItems = (SIZE_T)lParam;
1211 |
1212 | HexView->TotalLines = HexView->TotalItems / 16;
1213 |
1214 | if (HexView->TotalItems % 16) {
1215 | HexView->TotalLines += 1;
1216 | }
1217 |
1218 | HexView->LongestLine = ((HexView->ExStyle & HVS_ADDRESS64) ? NUMBEROF_CHARS_IN_FIRST_COLUMN_64BIT : NUMBEROF_CHARS_IN_FIRST_COLUMN_32BIT) + NUMBEROF_CHARS_IN_SECOND_COLUMN + NUMBEROF_CHARS_IN_THIRD_COLUMN;
1219 | }
1220 |
1221 | HexView->NumberOfItem = 0;
1222 | HexView->PositionInItem = 0;
1223 |
1224 | HexView->SelectionStart = 0;
1225 | HexView->SelectionEnd = 0;
1226 | HexView->Flags &= ~HVF_SELECTED;
1227 |
1228 | HexView->ActiveColumn = COLUMN_DATA;
1229 |
1230 | HexView->VscrollPos = 0;
1231 | HexView->VscrollMax = max(HexView->TotalLines - 1, 0);
1232 | HexView->HscrollPos = 0;
1233 | HexView->HscrollMax = max(HexView->LongestLine - 1, 0);
1234 |
1235 | HexView_SetPositionOfColumns(HexView);
1236 |
1237 | HexView_SetScrollInfo(hWnd, HexView);
1238 | HexView_SetCaret(hWnd, HexView);
1239 |
1240 | InvalidateRect(hWnd, NULL, FALSE);
1241 | break;
1242 | }
1243 | case HVM_GETSEL:
1244 | {
1245 | if (lParam) {
1246 |
1247 | ((PBYTERANGE)lParam)->Min = min(HexView->SelectionStart, HexView->SelectionEnd);
1248 | ((PBYTERANGE)lParam)->Max = max(HexView->SelectionStart, HexView->SelectionEnd);
1249 |
1250 | if (HexView->Flags & HVF_SELECTED) {
1251 |
1252 | ((PBYTERANGE)lParam)->Max += 1;
1253 | }
1254 | }
1255 | break;
1256 | }
1257 | case HVM_SETSEL:
1258 | {
1259 | if (lParam) {
1260 |
1261 | if ((((PBYTERANGE)lParam)->Min >= 0 && ((PBYTERANGE)lParam)->Min < HexView->TotalItems) &&
1262 | (((PBYTERANGE)lParam)->Max >= 0 && ((PBYTERANGE)lParam)->Max <= HexView->TotalItems)) {
1263 |
1264 | HexView->SelectionStart = ((PBYTERANGE)lParam)->Min;
1265 | HexView->SelectionEnd = ((PBYTERANGE)lParam)->Max;
1266 |
1267 | if (((PBYTERANGE)lParam)->Min != ((PBYTERANGE)lParam)->Max) {
1268 |
1269 | HexView->SelectionEnd -= 1;
1270 | HexView->Flags |= HVF_SELECTED;
1271 | }
1272 | else {
1273 |
1274 | HexView->Flags &= ~HVF_SELECTED;
1275 | }
1276 |
1277 | HexView->NumberOfItem = HexView->SelectionStart;
1278 | HexView->PositionInItem = 0;
1279 |
1280 | HexView->VscrollPos = min((LONG_PTR)(HexView->NumberOfItem / 16), max(0, HexView->VscrollMax - HexView->VisibleLines + 1));
1281 |
1282 | HexView_SetScrollInfo(hWnd, HexView);
1283 | HexView_SetCaret(hWnd, HexView);
1284 |
1285 | InvalidateRect(hWnd, NULL, FALSE);
1286 | }
1287 | }
1288 | break;
1289 | }
1290 | case HVM_SETTEXTCOLOR:
1291 | {
1292 | HexView->clrText = (COLORREF)lParam;
1293 | InvalidateRect(hWnd, NULL, FALSE);
1294 | break;
1295 | }
1296 | case HVM_SETBKCOLOR:
1297 | {
1298 | HexView->clrTextBackground = (COLORREF)lParam;
1299 | InvalidateRect(hWnd, NULL, FALSE);
1300 | break;
1301 | }
1302 | case HVM_SETSELBKCOLOR:
1303 | {
1304 | HexView->clrSelectedTextBackground = (COLORREF)lParam;
1305 | InvalidateRect(hWnd, NULL, FALSE);
1306 | break;
1307 | }
1308 | case HVM_SETMODIFIEDCOLOR:
1309 | {
1310 | HexView->clrModifiedText = (COLORREF)lParam;
1311 | InvalidateRect(hWnd, NULL, FALSE);
1312 | break;
1313 | }
1314 | case WM_DESTROY:
1315 | {
1316 | if (HexView) {
1317 |
1318 | if (HexView->Flags & HVF_FONTCREATED) {
1319 |
1320 | DeleteObject(HexView->hFont);
1321 | }
1322 |
1323 | HeapFree(GetProcessHeap(), 0, HexView);
1324 | }
1325 | break;
1326 | }
1327 | default:
1328 | return DefWindowProc(hWnd, message, wParam, lParam);
1329 | break;
1330 | }
1331 |
1332 | return 0;
1333 | }
1334 |
1335 | HWND
1336 | CreateHexView(
1337 | _In_ HWND hWndParent
1338 | )
1339 | {
1340 | HWND hWnd;
1341 |
1342 | hWnd = CreateWindowEx(0,
1343 | _T("HexView"),
1344 | NULL,
1345 | WS_CHILD |
1346 | WS_VISIBLE,
1347 | 0,
1348 | 0,
1349 | 0,
1350 | 0,
1351 | hWndParent,
1352 | 0,
1353 | GetModuleHandle(NULL),
1354 | NULL);
1355 |
1356 | return hWnd;
1357 | }
1358 |
1359 | VOID
1360 | RegisterClassHexView(
1361 | VOID
1362 | )
1363 | {
1364 | WNDCLASSEX wcex = {0};
1365 |
1366 | wcex.cbSize = sizeof(WNDCLASSEX);
1367 | wcex.lpfnWndProc = HexViewProc;
1368 | wcex.hInstance = GetModuleHandle(NULL);
1369 | wcex.hCursor = LoadCursor(NULL, IDC_IBEAM);
1370 | wcex.lpszClassName = _T("HexView");
1371 |
1372 | RegisterClassEx(&wcex);
1373 | }
--------------------------------------------------------------------------------
/HexEdit/HexView.h:
--------------------------------------------------------------------------------
1 | /*++
2 |
3 | Copyright (c) Andrey Bazhan
4 |
5 | --*/
6 |
7 | #pragma once
8 | #include "stdafx.h"
9 |
10 |
11 | #define HVM_SETTEXTCOLOR (WM_USER + 0)
12 | #define HVM_SETBKCOLOR (WM_USER + 1)
13 | #define HVM_SETSELBKCOLOR (WM_USER + 2)
14 | #define HVM_SETMODIFIEDCOLOR (WM_USER + 3)
15 | #define HVM_SETEXTENDEDSTYLE (WM_USER + 4)
16 | #define HVM_SETITEMCOUNT (WM_USER + 5)
17 | #define HVM_GETSEL (WM_USER + 6)
18 | #define HVM_SETSEL (WM_USER + 7)
19 |
20 |
21 | #define HVN_GETDISPINFO (WMN_FIRST - 0)
22 | #define HVN_ITEMCHANGING (WMN_FIRST - 1)
23 |
24 |
25 | //
26 | // Mask of an item
27 | //
28 |
29 | #define HVIF_ADDRESS 0x0001
30 | #define HVIF_BYTE 0x0002
31 |
32 | //
33 | // State of an item
34 | //
35 |
36 | #define HVIS_MODIFIED 0x0001
37 |
38 | //
39 | // Extended styles
40 | //
41 |
42 | #define HVS_ADDRESS64 0x0001
43 | #define HVS_READONLY 0x0002
44 |
45 | //
46 | // States of the control
47 | //
48 |
49 | #define HVF_FONTCREATED 0x0001
50 | #define HVF_CARETVISIBLE 0x0002
51 | #define HVF_SELECTED 0x0004
52 |
53 |
54 | enum Column {
55 | COLUMN_DATA = 1,
56 | COLUMN_VALUE
57 | };
58 |
59 | typedef struct _HEXVIEW {
60 | int Line1; // Start of the COLUMN_DATA
61 | int Line2; // Start of the COLUMN_VALUE
62 |
63 | int VisibleLines;
64 | LONG_PTR TotalLines;
65 | int VisibleChars;
66 | int LongestLine;
67 |
68 | LONG_PTR VscrollPos;
69 | LONG_PTR VscrollMax;
70 | int HscrollPos;
71 | int HscrollMax;
72 |
73 | int HeightChar;
74 | int WidthChar;
75 | int HeightView;
76 | int WidthView;
77 |
78 | int ActiveColumn; // COLUMN_DATA or COLUMN_VALUE
79 |
80 | SIZE_T TotalItems;
81 | SIZE_T NumberOfItem;
82 | UINT PositionInItem; // 0 = HINIBBLE; 1 = LONIBBLE
83 |
84 | SIZE_T SelectionStart;
85 | SIZE_T SelectionEnd;
86 |
87 | DWORD Flags;
88 | DWORD ExStyle;
89 |
90 | HFONT hFont;
91 |
92 | COLORREF clrText;
93 | COLORREF clrTextBackground;
94 | COLORREF clrSelectedTextBackground;
95 | COLORREF clrModifiedText;
96 | } HEXVIEW, *PHEXVIEW;
97 |
98 | typedef struct _HVITEM {
99 | UINT Mask;
100 | UINT State;
101 | ULONG64 Address;
102 | SIZE_T NumberOfItem;
103 | BYTE Value;
104 | } HVITEM, *PHVITEM;
105 |
106 | typedef struct _NMHVDISPINFO {
107 | NMHDR NmHdr;
108 | HVITEM Item;
109 | } NMHVDISPINFO, *PNMHVDISPINFO;
110 |
111 | typedef struct _NMHEXVIEW {
112 | NMHDR NmHdr;
113 | HVITEM Item;
114 | } NMHEXVIEW, *PNMHEXVIEW;
115 |
116 | typedef struct _BYTERANGE {
117 | SIZE_T Min;
118 | SIZE_T Max;
119 | } BYTERANGE, *PBYTERANGE;
120 |
121 | HWND
122 | CreateHexView(
123 | _In_ HWND hWndParent
124 | );
125 |
126 | VOID
127 | RegisterClassHexView(
128 | VOID
129 | );
130 |
--------------------------------------------------------------------------------
/HexEdit/Resource.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreyBazhan/HexEdit/5346c62adb467437429385f667e35d0198a01d44/HexEdit/Resource.h
--------------------------------------------------------------------------------
/HexEdit/Version.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreyBazhan/HexEdit/5346c62adb467437429385f667e35d0198a01d44/HexEdit/Version.rc
--------------------------------------------------------------------------------
/HexEdit/Version.txt:
--------------------------------------------------------------------------------
1 | #define BINVERSION 1,0,0,0
2 | #define STRVERSION "1.0"
3 | #define YEAR "2014"
4 |
--------------------------------------------------------------------------------
/HexEdit/small.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndreyBazhan/HexEdit/5346c62adb467437429385f667e35d0198a01d44/HexEdit/small.ico
--------------------------------------------------------------------------------
/HexEdit/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // Windows Application.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "stdafx.h"
6 |
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 |
--------------------------------------------------------------------------------
/HexEdit/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 |
8 | #include "targetver.h"
9 |
10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
11 | // Windows Header Files:
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | // C RunTime Header Files
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 |
27 | // TODO: reference additional headers your program requires here
28 |
--------------------------------------------------------------------------------
/HexEdit/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Andrey Bazhan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HexEdit
2 |
3 | Hexadecimal editor.
4 |
5 |
--------------------------------------------------------------------------------