Edit Controls ------------------------------------------------------------------------------- By Bill T. March 14, 1999 Introduction: ------------------------------------------------------------------------------- A control is a child window an application uses in with another window to perform simple input and output tasks. Controls are most often used within dialog boxes, but they can also be used in other windows. An edit control is a rectangular control window typically used in a dialog box to permit the user to enter and edit text from the keyboard. This article will show how to easily create a simple text editor by using an edit control. The control itself provides most of the needed functionality, and only a small amount of actual code is needed. In order make sure the common controls library is loaded, so that you can use them, you should call the InitCommonControls function. An edit control can send notification messages to its parent window in the form of WM_COMMAND messages. A parent window can send messages to an edit control in a dialog box by calling the SendDlgItemMessage function. Files and Tools: ------------------------------------------------------------------------------- Here are some things you will need to use this tutorial.... MASM (Get the MASM32 package) Borlands MAKE (if you wish to use my makefile) Borlands BRCC32 (i dont know why, but i still use borland resource compiler) Borlands H2ASH (not really necessary... easy way to convert .h to .inc) The source code (lordlucifer.cjb.net/tutorials/edit_tut.zip) Win32 API reference WinMain ------------------------------------------------------------------------------- This function is where the execution effectively begins... It initializes the various window controls, files, and keyboard accelerators. Keyboard accelerators are basically keyboard shortcuts to menu items. To use accelerators, an accelerator table is created as a resource, in the following basic form: acceltablename ACCELERATORS { event, idvalue, [type] [options] ... } event corresponds to the key to be used. It can be of the form "c", an integer value representing a char, or a virtual-key value. idvalue integer which specifies the ID type specifies VIRTKEY or ASCII options NOINVERT, ALT, SHIFT, CONTROL WinMain is also the home of the message loop. Here, the GetMessage function grabs the next message from the message queue. The TranslateAccelerator function then checks the message to see if it is an accelerator. If it is, it handles the message. If not, execution is passed to the TranslateMessage and DispatchMessage functions which sends the message to the appropriate window procedure. The message loop is broken when GetMessage retrieves the WM_QUIT message. InitWindow ------------------------------------------------------------------------------- This function creates and shows the main application window. To create a window, first you must register a window class for that window. This is done by filling in a WNDCLASSEX structure and passing it to the RegisterClassEx function. Then the CreateWindowEx function is called, using the newly created window class to create and show the window. InitEditControl ------------------------------------------------------------------------------- This procedure initializes the Edit control and sizes it to fit inside the main window. All edit controls belong to the window class "EDIT". This class name is specified in the call to CreateWindowEx. With common controls, you do not define and register your own class, you use the pre-defined window classes, defined in the commctrl.dll. The edit window can have a variety of styles. In addition to the standard window styles, the edit control has sever additional styles: ES_MULTILINE: control can have more than one line (default is 1 line only) ES_AUTOVSCROLL, ES_AUTOHSCROLL: If the text to be displayed exceeds the size of the window, these flags tell the control to automatically scroll the text into view ES_LEFT, ES_CENTER, ES_RIGHT: These set the text alignment, and apply only to multiline edit controls. ES_LOWERCASE, ES_UPPERCASE: Sets the text to all lowercase or uppercase characters, respectively. ES_OEMCONVERT: Converts the text into a specific character set. ES_NUMBER: Limits text input to numbers only. ES_NOHIDESEL: Specifies the selected text is not hidden when the control loses focus. ES_READONLY: Makes the text read-only. ES_PASSWORD: Displays all characters as * (or other user defined character) ES_WANTRETURN: Specifies that a return is inserted when the enter key is pressed, for multiline controls only. InitFile ------------------------------------------------------------------------------- In this function, I get the command line arguments, and if a file is specified, it is loaded into the editor. If no file is specified, the editor begins with a new document. To get the command line arguments, I have created another function called GetCommandLineArgs. This uses the GetCommandLine API function to get the entire command line. I then parse the string to get the arguments only. If the program is called with no arguments, the command line is returned from GetCommandLine as a string. If it has arguments, or is called from a directory with spaces, the command line is returned as a string with the full exe's path in quotes, and with the arguments following. MainWndProc ------------------------------------------------------------------------------- This function is the window procedure for the main application window. This is specified in the lpfnWndProc member of the WNDCLASSEX struct, which is passed to the RegisterClassEx function. This is a callback function, called by windows and requiring the following form: MainWndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD ... MainWndProc endp The hWnd parameter specifies the window handle that the message is sent to. uMsg specifies the message sent. wParam and lParam have varying meanings, depending on which message is being sent. The window procedure is responsible for handling all of the messages sent to the application window. Here, the editing functionality, menu commands, window re-sizing and window termination are handled here. I only handle the messages which I need for this application. All other messages are passed to the DefWindowProc API function, so they are properly dealt with and not lost. The WM_DESTROY message should always be handled. This message is sent when the application window is closed. The handler then calls the PostQuitMessage API function, which is used to terminate the application. Failure to call this will result in the window disappearing but the application remaining in memory. The WM_COMMAND message is sent whenever a menu item is chosen, or an accelerator key is pressed. The values of lParam and wParam for the WM_COMMAND are: wNotifyCode = HIWORD(wParam) : notification code wID = LOWORD(wParam) : item, control, or accelerator identifier hwndCtl = lParam : handle of control which message is from The WM_COMMAND handler is where all of the interface to the edit control occurs. Edit Control Messages ------------------------------------------------------------------------------- EM_SETSEL is used to set the selection in the edit control. wParam is the starting character position of the selection, and lParam is the ending position. If wParam = 0 and lParam = -1, all the text is selected. If wParam = -1, no text is selected (or a previous selection is de-selected). EM_SETMODIFY sets or clears the modified flag of the edit control. This flag indicated whether the text has changed. wParam specified the true/false value to set the modified flag to. This is automatically set when the text is first changed. The EM_GETMODIFY message can be used to retrieve the modified flag. WM_COPY, WM_CUT, WM_PASTE, WM_CLEAR these messages affect the currently selected text, and perform their respective actions. For each, the wParam and lParam parameters are set to 0. EM_UNDO is used to undo the last edit operation. A second call to WM_UNDO will undo the undo... There are many other edit control messages which you can use (I am just too lazy to write about them all...) For further reading, consult the API reference... EditOpenFile / FileOpen ------------------------------------------------------------------------------- These functions are used to open a file, and load it into the edit control. EditOpenFile first calls the GetOpenFileName API function to get the filename to open. For this function, you must first fill the OPENFILENAME structure, which contains the information needed to initialize the Open common dialog box. The GetOpenFilaName function returns TRUE if a file was selected, FALSE otherwise. The selected file is returned in the lpstrFile member of the OPENFILENAME structure. This filename is then passed to the FileOpen function, which actually opens the file, and puts it into the edit controls text buffer. It begins by opening the file with the CreateFile API, using the OPEN_EXISTING parameter. Next, the file size is determined, so it is known how many bytes to allocate to store it. The memory buffer is allocated using the HeapAlloc API function, and Read File is used to copy the contents of the file into the newly created buffer. This buffer is then copied to the edit control, by sending it the WM_SETTEXT message. This function ends by closing the file, and releasing the memory buffer. EditSaveFile / FileSave ------------------------------------------------------------------------------- These functions are very similar to their open counterparts, the only differences being, instead of reading from the file and writing to the edit control, it is saved to the file and read from the control. ConfirmOperation ------------------------------------------------------------------------------- This is a simple utility function which i use to confirm that the user really wants to do what he says... The function checks to see if the edit control has been modified, and if so, it shows a yes/no message box. This is done by using the MessageBox API with the MB_YESNO option. It then returns IDYES if the user chooses yes (or the control has not been modified), or IDNO, if the user chooses no. SetTitle ------------------------------------------------------------------------------- This is another utility function which sets the application title to show the filename of the file currently being edited, or Untitled for a new file. To do this, it sends the WM_SETTEXT message to the main application window, with the new title as the lParam. Conclusion ------------------------------------------------------------------------------- Hmm.. this turned out to be not much of a tutorial on edit controls... as I have added a lot of non-edit control related code in an attempt to prevent the example program from being a completely useless app... Instead it is only a mostly useless app... Of course, for a detailed description of Edit Controls, read the Windows API reference. ----------------------------------------------------------------------------- Copyright (C) 1999 Bill T. (billasm@usa.net)