#include "framework.h" #include "WindowsProject3.h" #include #include #include #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance WCHAR szTitle[MAX_LOADSTRING]; // The title bar text WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Hex editor globals HWND hHexEdit = NULL; WNDPROC oldEditProc = NULL; const int BYTES_PER_LINE = 16; const int TOTAL_LINES = 100; // Total lines of hex data int currentScrollPos = 0; // Sample hex data BYTE hexData[BYTES_PER_LINE * TOTAL_LINES]; // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK HexEditProc(HWND, UINT, WPARAM, LPARAM); void UpdateHexDisplay(HWND hEdit, int scrollPos); void InitializeHexData(); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. // Initialize global strings LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_WINDOWSPROJECT3, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT3)); MSG msg; // Main message loop: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT3)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT3); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex); } // // FUNCTION: InitInstance(HINSTANCE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // Store instance handle in our global variable HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 800, 600, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { // Initialize hex data InitializeHexData(); // Create the edit control with vertical scrollbar hHexEdit = CreateWindowExW( 0, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER | ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL, 10, 10, 760, 500, hWnd, (HMENU)1001, hInst, NULL ); if (hHexEdit) { // Set a fixed-width font for better hex display HFONT hFont = CreateFontW( 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"Courier New" ); SendMessage(hHexEdit, WM_SETFONT, (WPARAM)hFont, TRUE); // Subclass the edit control oldEditProc = (WNDPROC)SetWindowLongPtr(hHexEdit, GWLP_WNDPROC, (LONG_PTR)HexEditProc); // Set up scrollbar info SCROLLINFO si = { 0 }; si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMin = 0; si.nMax = TOTAL_LINES - 1; si.nPage = 20; // Visible lines si.nPos = 0; SetScrollInfo(hHexEdit, SB_VERT, &si, TRUE); // Initial display UpdateHexDisplay(hHexEdit, 0); } } break; case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_VSCROLL: { // Handle scrollbar messages SCROLLINFO si = { 0 }; si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_ALL; GetScrollInfo(hHexEdit, SB_VERT, &si); int newPos = si.nPos; switch (LOWORD(wParam)) { case SB_LINEUP: newPos -= 1; break; case SB_LINEDOWN: newPos += 1; break; case SB_PAGEUP: newPos -= si.nPage; break; case SB_PAGEDOWN: newPos += si.nPage; break; case SB_THUMBTRACK: case SB_THUMBPOSITION: newPos = HIWORD(wParam); break; } // Clamp the position newPos = max(0, min(newPos, si.nMax - (int)si.nPage + 1)); if (newPos != si.nPos) { currentScrollPos = newPos; si.nPos = newPos; si.fMask = SIF_POS; SetScrollInfo(hHexEdit, SB_VERT, &si, TRUE); UpdateHexDisplay(hHexEdit, newPos); } } break; case WM_SIZE: { // Resize the edit control when window is resized if (hHexEdit) { RECT rect; GetClientRect(hWnd, &rect); MoveWindow(hHexEdit, 10, 10, rect.right - 20, rect.bottom - 20, TRUE); } } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code that uses hdc here... EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for about box. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } // // FUNCTION: HexEditProc(HWND, UINT, WPARAM, LPARAM) // // PURPOSE: Subclassed window procedure for the hex edit control // LRESULT CALLBACK HexEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_VSCROLL: // Forward scroll messages to parent return SendMessage(GetParent(hWnd), WM_VSCROLL, wParam, lParam); case WM_MOUSEWHEEL: { // Handle mouse wheel scrolling int delta = GET_WHEEL_DELTA_WPARAM(wParam); int scrollAmount = delta / WHEEL_DELTA; if (scrollAmount > 0) { SendMessage(GetParent(hWnd), WM_VSCROLL, SB_LINEUP, 0); } else if (scrollAmount < 0) { SendMessage(GetParent(hWnd), WM_VSCROLL, SB_LINEDOWN, 0); } return 0; } } return CallWindowProc(oldEditProc, hWnd, message, wParam, lParam); } // // FUNCTION: InitializeHexData() // // PURPOSE: Initialize sample hex data // void InitializeHexData() { for (int i = 0; i < BYTES_PER_LINE * TOTAL_LINES; i++) { hexData[i] = (BYTE)(i % 256); } } // // FUNCTION: UpdateHexDisplay(HWND, int) // // PURPOSE: Update the hex editor display based on scroll position // void UpdateHexDisplay(HWND hEdit, int scrollPos) { std::wstringstream ss; // Display 20 lines at a time int startLine = scrollPos; int endLine = min(startLine + 20, TOTAL_LINES); for (int line = startLine; line < endLine; line++) { // Address ss << std::hex << std::uppercase << std::setfill(L'0') << std::setw(8) << (line * BYTES_PER_LINE) << L" "; // Hex bytes for (int col = 0; col < BYTES_PER_LINE; col++) { int index = line * BYTES_PER_LINE + col; ss << std::setw(2) << (int)hexData[index] << L" "; if (col == 7) ss << L" "; // Extra space in the middle } ss << L" "; // ASCII representation for (int col = 0; col < BYTES_PER_LINE; col++) { int index = line * BYTES_PER_LINE + col; BYTE b = hexData[index]; if (b >= 32 && b <= 126) ss << (wchar_t)b; else ss << L"."; } ss << L"\r\n"; } SetWindowTextW(hEdit, ss.str().c_str()); }