In this tutorial w'ell learn the basic file handling methods.we'll create a simple text editor which can open and save files.
To open and save a file we must fill the OPENFILENAME structure and pass it as parameter for necessary functions.
The members of OPENFILENAME structure are
OPENFILENAME STRUCT
lStructSize DWORD ?
hwndOwner HWND ?
hInstance HINSTANCE ?
lpstrFilter LPCSTR ?
lpstrCustomFilter LPSTR ?
nMaxCustFilter DWORD ?
nFilterIndex DWORD ?
lpstrFile LPSTR ?
nMaxFile DWORD ?
lpstrFileTitle LPSTR ?
nMaxFileTitle DWORD ?
lpstrInitialDir LPCSTR ?
lpstrTitle LPCSTR ?
Flags DWORD ?
nFileOffset WORD ?
nFileExtension WORD ?
lpstrDefExt LPCSTR ?
lCustData LPARAM ?
lpfnHook DWORD ?
lpTemplateName LPCSTR ?
OPENFILENAME ENDS
OPENFILENAME structure has many members but filling the necessary members is enough for us. The necessary members of structure are
lStructSize ->size of the OPENFILENAME structure
hwndOwner ->handle of our main window.
hInstance ->our hInstance
lpstrFilter ->Pointer to a buffer containing pairs of null-terminated filter strings. we can also use NULL but it won't filter our files.
lpstrFile ->we pass the offset of buffer where the filename with fullpath name is stored
nMaxFile ->the size of the lpstrFile buffer.The buffer should be at least 256 characters long.
Flags ->A set of bit flags you can use to initialize the dialog box which determines the style and charecteristics of dialog box.
The above are the frequently filled members of OPENFILENAME structure
lpstrTitle ->Pointer to a string to be placed in the title bar of the dialog box. If NULL or not initialized it use system default (Open)
lpstrInitialDir ->A pointer to the string that specifies initial file directory.If not set it uses the current directory
nFileOffset ->The full file name is stored here after selecting a file from open file dialog box.
lpfnHook ->Pointer to the hook procedure, often not used.
After filling necessary members we can call GetOpenFileName or GetSaveFileName.
I've attached the full source code of the program, we'll discuss only necessary procedures here,
DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rect:RECT
LOCAL SizeReadWrite:DWORD
.if uMsg==WM_INITDIALOG
invoke GetDlgItem,hWnd,IDC_EDIT
mov hwndEdit,eax
;Fill the members of ofn structure
mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hWndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
.elseif uMsg==WM_SIZE
invoke GetClientRect,hWnd,addr rect
invoke MoveWindow,hwndEdit,0,0,rect.right,rect.bottom,TRUE
.elseif uMsg==WM_COMMAND
.if lParam==0
mov eax,wParam
.if ax==IDM_OPEN
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile,ADDR buffer,\
GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE,\
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFile,eax
invoke Allocandlock
invoke ReadFile,hFile,pMemory,MEMSIZE-1,ADDR SizeReadWrite,NULL
invoke SendMessage,hwndEdit,WM_SETTEXT,NULL,pMemory
invoke SetTitle,hWnd
invoke Cleanup
.endif
.elseif ax==IDM_SAVE
mov ofn.Flags,OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetSaveFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile,ADDR buffer,\
GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE,\
NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFile,eax
invoke Allocandlock
invoke SendMessage,hwndEdit,WM_GETTEXT,MEMSIZE-1,pMemory
mov ebx,eax
invoke WriteFile,hFile,pMemory,ebx,ADDR SizeReadWrite,NULL
invoke SetTitle,hWnd
invoke Cleanup
.endif
.elseif ax==IDM_NEW
invoke Cleanup
invoke SetWindowText,hwndEdit,NULL
invoke SetWindowText,hWnd,addr AppName
.elseif ax==IDM_EXIT
invoke PostMessage,hWnd,WM_CLOSE,0,0
.elseif ax==IDM_ABOUT
invoke ShellAbout,hWnd,addr AppName,addr Details,0
.endif
.endif
.elseif uMsg==WM_CLOSE
invoke EndDialog,hWnd,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
Ret
DlgProc endp
Cleanup proc
invoke CloseHandle,hFile
invoke GlobalUnlock,pMemory
invoke GlobalFree,hMemory
xor eax,eax
Ret
Cleanup endp
Allocandlock proc
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE
mov hMemory,eax
invoke GlobalLock,hMemory
mov pMemory,eax
xor eax,eax
Ret
Allocandlock endp
SetTitle proc hWin:HWND
mov eax,OFFSET buffer
movzx edx,ofn.nFileOffset
add eax,edx
invoke SetWindowText,hWin,eax
xor eax,eax
Ret
SetTitle endp
In this program i have used four procedures so we must include a prototype for every procedure in the beginning of the program.
It is good to have many procedures in our programs to minimize the repetition of the same code again and again.
ok, we'll analyse the above program.
LOCAL rect:RECT
LOCAL SizeReadWrite:DWORD
.if uMsg==WM_INITDIALOG
invoke GetDlgItem,hWnd,IDC_EDIT
mov hwndEdit,eax
;Fill the members of ofn structure
mov ofn.lStructSize,SIZEOF ofn
push hWnd
pop ofn.hWndOwner
push hInstance
pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,MAXSIZE
As we know dialog boxes dosen't send WM_CREATE message instead they use WM_INITDIALOG message. This seems the suitable place for filling the necessary members of openfilename structure and get the handles for the controls we created in the resource editor.
We use GetDlgItem to get handle of our editcontrol. we fill the members of ofn as discussed above.
we also define two local variables in stack for later use.
.elseif uMsg==WM_SIZE invoke GetClientRect,hWnd,addr rect invoke MoveWindow,hwndEdit,0,0,rect.right,rect.bottom,TRUE
Every window recieves WM_SIZE message after once created we use this oppurtunity for resizing our edit control to the whole window size. We call GetClientRect API which retrieves the coordinates of a window's client area the right and bottom members contain the width and height of the window.Then we call MoveWindow function to resize our edit control to the client area size.(we can also use GetWindowRect API function)
.elseif uMsg==WM_COMMAND .if lParam==0 mov eax,wParam .if ax==IDM_OPEN mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY invoke GetOpenFileName, ADDR ofn .if eax==TRUE invoke CreateFile,ADDR buffer,\ GENERIC_READ or GENERIC_WRITE ,\ FILE_SHARE_READ or FILE_SHARE_WRITE,\ NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,\ NULL mov hFile,eax
WM_COMMAND message is sent when the user selects a command item from a menu.we confirm that message is send from the menu by checking the lParam is NULL. Incase of message from button controls and others things we recive handle of the button control in lParam so it won't be NULL.We have selected Open in menu item.
Then its time set out flags for our ofn structure
OFN_PATHMUSTEXIST -> specifies user can type only valid path and filenames.
OFN_FILEMUSTEXIST -> Specifies that the user can type only names of existing files in the File Name entry field.
OFN_LONGNAMES -> this flag cause dialogbox to use long file names
OFN_EXPLORER -> To use explorer like interface in Dialogbox
OFN_HIDEREADONLY ->hides readonly checkbox
Everything is set it's time to call GetOpenFileName function which returns TRUE in eax if a file is selected.Then we create a file with Createfile API function in the access modes we use GENERIC_READ or GENERIC_WRITE as the term explains we can read and write data in file, To set how the file is shared we use FILE_SHARE_READ or FILE_SHARE_WRITE,we dont use any security attributes so set as NULL.
Then we set what should be done incase of file exist and does not exist.
OPEN_EXISTING ->Opens the file. The function fails if the file does not exist.
FILE_ATTRIBUTE_ARCHIVE The file should be archived. Applications use this attribute to mark files for backup or removal.and we use NULL for the flags since we dont need any. Then we save the handle of the file.
invoke Allocandlock
The we use our procedure we defined which contains the code to allocate and lock file in memory.
Allocandlock proc
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE
mov hMemory,eax
invoke GlobalLock,hMemory
mov pMemory,eax
xor eax,eax
Ret
Allocandlock endp
We use GlobalAlloc function which allocates the specified number of bytes from the heap.MEM_MOVEABLE - Allocates movable memory,
GMEM_ZEROINIT - Initializes memory contents to zero.
Then we store the handle of the memory.The GlobalLock function locks a global memory object and returns a pointer we store it as pointer for our memory.we clear contents of eax and return from the procedure.
invoke ReadFile,hFile,pMemory,MEMSIZE-1,ADDR SizeReadWrite,NULL invoke SendMessage,hwndEdit,WM_SETTEXT,NULL,pMemory
ReadFile function read data from the file from the position indicated by the pointer. we specify the 'number of bytes to be read' in which the total memory block that can be allocated by GlobalAlloc function is 65536 minus 1(ie,MEMSIZE-1 would be 65534) nearly full of the memory block that can be allocated by GlobalAlloc function.number of bytes read is where the function stores how many bytes were actually read.
Then we set the text in our edit control with WM_SETTEXT message.
invoke SetTitle,hWnd invoke Cleanup
After displaying the text we should change the title of window and clean the mess (Free our memory). For thet i use two procedures
SetTitle proc hWin:HWND
mov eax,OFFSET buffer
movzx edx,ofn.nFileOffset
add eax,edx
invoke SetWindowText,hWin,eax
xor eax,eax
Ret
SetTitle endp
Cleanup proc
invoke CloseHandle,hFile
invoke GlobalUnlock,pMemory
invoke GlobalFree,hMemory
xor eax,eax
Ret
Cleanup endp
In the SetTitle proc add the contents of buffer and ofn.nFileOffset to obtain the name of the file we opened. In the cleanup proc we have closed the handle, Unlocked the memory and freed the memory.
.elseif ax==IDM_SAVE
mov ofn.Flags,OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetSaveFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile,ADDR buffer,\
GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE,\
NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFile,eax
invoke Allocandlock
invoke SendMessage,hwndEdit,WM_GETTEXT,MEMSIZE-1,pMemory
mov ebx,eax
invoke WriteFile,hFile,pMemory,ebx,ADDR SizeReadWrite,NULL
invoke SetTitle,hWnd
invoke Cleanup
.endif
Similarly we set flags to call GetSaveFileName function and do same things as we did while opening a file, but we have used WM_GETTEXT since we are reading the contents of editbox and using WriteFile function we save the contents.
.elseif ax==IDM_NEW invoke Cleanup invoke SetWindowText,hwndEdit,NULL invoke SetWindowText,hWnd,addr AppName .elseif ax==IDM_EXIT invoke PostMessage,hWnd,WM_CLOSE,0,0 .elseif ax==IDM_ABOUT invoke ShellAbout,hWnd,addr AppName,addr Details,0
If we selected new in menuitem we clean the handles and free the memory, delete contents of edit control and restore our title bar.
In case we clicked Exit we post WM_CLOSE message then WM_CLOSE message will be placed in queue, when the turn comes program exits.
Finally if we clicked about we display the shell about box(predefined about box) with contents what we need to display.
Attached File(s)
-
Dic.zip (15.07K)
Number of downloads: 135





MultiQuote






|