Welcome to a new season of the CSIG, a Special Interest Group of the ACGNJ. The subject for this month is an introduction to C++ Windows programming using the example that we started last month. This is a Hex Dump Utility for displaying the information inside any file. The "command line code" (sometimes call DOS code) has been merged with Windows code created by the MFC (Microsoft Foundation Classes), SDI (Single Document Interface) application generator in the Microsoft Visual C++ version 6.0 compiler. I will be discussing the steps required to make this transition.
The first pass at developing this program proceeded quite smoothly and I had a working program in a short period of time. There were however some important improvements that I wanted to make. This leads us into the second part of the meeting presentation, "The OnIdle() function". This is a very exciting programming area which can mean a major difference in the quality of the program as seen by the user.
Here's the problem: when the source file for the hex dump is selected, the program must then read and translate the data into hex code. On a large file this can take many seconds or even minutes. Meanwhile the user is just staring at a blank window. Wouldn't it be nice if the user could actually start using the utility to inspect the data while in the background the program would continue to read the data until it reached the end of the file. This can be accomplished and I will show how to do it.
The program allows the viewing of information within otherwise unreadable files such as executables, zip files, bitmap files, etc. As shown in the example, it produces a hexadecimal dump of the target file.
void CDumpwDoc::DoBackgroundRead() // *** ADDED__CODE *** { POSITION pos = GetFirstViewPosition(); CDumpwView* pView = (CDumpwView* )GetNextView( pos ); if (mReadActive) { int n; unsigned char buff[100]; for (int i=0; i<64 && mNextLine < mLines; i++) { n = fread(buff,1,16, mFS1); pView->m_List.AddString(DoProcess(mNextLine, buff, n) ); mNextLine++; } if (mNextLine == mLines) { char text[100]; wsprintf(text, "%ld ( 0x%X ) bytes read.", mBytes, mBytes); fclose(mFS1); mFS1 = NULL; mReadActive = false; AfxMessageBox(text, MB_OK | MB_ICONINFORMATION, NULL); } } } // *** ADDED__CODE *** char * CDumpwDoc::DoProcess(int line, unsigned char *buff, int length) { static char output[100]; wsprintf(output, "%07X ",line * 16); hex_printf(output, buff, length); return output; } // // HEX PRINT A LINE // // *** ADDED__CODE *** void CDumpwDoc::hex_printf(char *pOut, unsigned char arg[], int count) { int i; char *p = pOut + strlen(pOut); for(i=0; i<count; i++) { wsprintf(p, "%02X ", arg[i]); // Hex bytes first p += 3; } for( ; i<16 ; i++) { strcat(p, " "); p += 3; } strcat(p, " "); p += 3; for(i=0; i<count; i++) *p++ = clean( arg[i]); // Now ascii info for( ; i<16 ; i++) *p++ = ' '; *p = 0; }