├── .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 | --------------------------------------------------------------------------------