windows sdk编程系列文章10 ---- 内存管理和文件输入输出.doc_第1页
windows sdk编程系列文章10 ---- 内存管理和文件输入输出.doc_第2页
windows sdk编程系列文章10 ---- 内存管理和文件输入输出.doc_第3页
windows sdk编程系列文章10 ---- 内存管理和文件输入输出.doc_第4页
windows sdk编程系列文章10 ---- 内存管理和文件输入输出.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

windows sdk编程系列文章 - 内存管理和文件输入输出2008-04-12 23:35本课中我们将学习基本的内存管理和文件输入/输出操作方面的知识。另外我们还将用上节课学的通用对话框作为我们的显示“设备”。理论:从用户的角度来看,WIN32的内存管理是非常简单和明了的。每一个应用程序都有自己独立的4G地址空间,这种内存模式叫做“平坦”型地址模式,所有的段寄存器或描述符都指向同样的起始地址,所有的地址偏移都是32位的长度,这样一个应用程序无须变换选择符就可以存取自己的多达4G的地址空间。这种内存管理模式是非常简洁而便于管理的,而且我们再不用和那些令人讨厌的“near”和“far”指针打交道了。在Win16下有两种主要类型的API:全局和局部。“全局”的API 分配在其他的段中,这样从内存角度来看他们是一些“far”(远)函数或者叫远过程调用,“局部”API只要和进程的堆打交道,所以把它们叫做“near”(近)函数或者近过程调用。而在WIN32中,这两种内存模式是相同的,无论您调用GlobalAlloc还是LocalAlloc,结果都是一样。至于分配和使用内存的过程都是一样的:1. 调用GlobalAlloc函数分配一块内存,该函数会返回分配的内存句柄。 2. 调用GlobalLock函数锁定内存块,该函数接受一个内存句柄作为参数,然后返回一个指向被锁定的内存块的指针。 3. 您可以用该指针来读写内存。 4. 调用GlobalUnlock函数来解锁先前被锁定的内存,该函数使得指向内存块的指针无效。 5. 调用GlobalFree函数来释放内存块。您必须传给该函数一个内存句柄。 在WIN32中您也可以用“Local”替代内存分配API函数带有“Global”字样的函数中的“Global”,也即用LocalAlloc、LocalLock等。在调用函数GlobalAlloc时使用GMEM_FIXED标志位可以更进一步简化操作。使用了该标志后,Global/LocalAlloc返回的是指向已分配内存的指针而不是句柄,这样也就不用调用Global/LocalLock来锁定内存了,释放内存时只要直接调用Global/LocalFree就可以了。不过在本课中我们只使用传统的方法,因为其它地方有许多的源代码是用这种方法写的。WIN32的文件输入/输出API和DOS下的从外表上看几乎一样,不同的只是把DOS下的中断方式处理文件输入/输出变成了对API函数的调用。以下是基本的步骤:1. 调用CreateFile函数生成一个文件,该函数可以应用在多方面,除了磁盘文件外,我们还可以用来打开通讯端口、管道、驱动程序或控制台。如果成功的话,会返回指向文件或设备的句柄。然后可以使用该句柄去完成对文件或设备操作。2. 调用SetFilePointer来把文件指针移到想读写的地方。. 3. 然后调用ReadFile 或 WriteFile来完成实际的读写。这些函数会自己处理文件和内存之间的数据传送,这样免得您自己去做分配内存等繁杂的琐事。 4. 调用CloseHandle来关闭文件。该函数接受一个先前打开的文件句柄。 例子:见光盘FirstWindow10下面的代码段演示了:打开一个“打开文件”对话框,用户可以选择打开一个文本文件,然后在一个编辑控件中打开该文本文件的内容,另外用户还可以编辑该文本文件的内容并选择保存。#include Windows.h#include tchar.hTCHAR ClassName = _T(Win32EditClass);TCHAR AppName = _T(Win32 Edit);TCHAR MenuName = _T(FirstMenu);TCHAR EditClass = _T(edit);HINSTANCE g_hInstance;#define IDM_OPEN 1#define IDM_SAVE 2#define IDM_EXIT 3#define MAXSIZE 260#define MEMSIZE 65535#define EditID 1OPENFILENAME g_ofn;TCHAR FilterString = _T(All Files0*.*0Text Files0*.txt0);TCHAR bufferMAXSIZE;HWND hwndEdit;HANDLE hFile;HANDLE hMemory;VOID* pMemory;DWORD SizeReadWrite;INT_PTR CALLBACK ProcWinMain( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) switch(Msg) case WM_CREATE: hwndEdit = CreateWindowEx(NULL,EditClass,NULL,WS_VISIBLE|WS_CHILD|ES_LEFT|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL, 0,0,0,0,hWnd,(HMENU)EditID, g_hInstance,NULL); SetFocus(hwndEdit); g_ofn.lStructSize = sizeof(g_ofn); g_ofn.hwndOwner = hWnd; g_ofn.hInstance = g_hInstance; g_ofn.lpstrFilter = FilterString; g_ofn.lpstrFile = buffer; g_ofn.nMaxFile = MAXSIZE; break; case WM_SIZE: MoveWindow(hwndEdit,0,0,LOWORD(lParam),HIWORD(lParam),TRUE); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_COMMAND: if(lParam = 0) if(LOWORD(wParam) = IDM_OPEN) g_ofn.Flags = OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST |OFN_LONGNAMES|OFN_EXPLORER|OFN_HIDEREADONLY; if(GetOpenFileName(&g_ofn) hFile = CreateFile(buffer,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE,NULL); hMemory = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,MEMSIZE); pMemory = GlobalLock(hMemory); ReadFile(hFile,pMemory,MEMSIZE-1,&SizeReadWrite,NULL); SendMessage(hwndEdit,WM_SETTEXT,NULL,(LPARAM)pMemory); CloseHandle(hFile); GlobalUnlock(pMemory); GlobalFree(hMemory); SetFocus(hwndEdit); else if(LOWORD(wParam) = IDM_SAVE) g_ofn.Flags = OFN_LONGNAMES|OFN_EXPLORER|OFN_HIDEREADONLY; if(GetSaveFileName(&g_ofn) hFile = CreateFile(buffer,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL); hMemory = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,MEMSIZE); pMemory = GlobalLock(hMemory); int nSize = SendMessage(hwndEdit,WM_GETTEXT,MEMSIZE-1,(LPARAM)pMemory); WriteFile(hFile,pMemory,nSize,&SizeReadWrite,NULL); CloseHandle(hFile); GlobalUnlock(pMemory); GlobalFree(hMemory); SetFocus(hwndEdit); else DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd,Msg,wParam,lParam); return 0;int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) WNDCLASSEX wc; MSG msg; HWND hWnd; g_hInstance = hInstance; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = ProcWinMain; wc.cbClsExtra = NULL; wc.cbWndExtra = NULL; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = MenuName; wc.lpszClassName = ClassName; wc.hIcon = wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL,IDC_ARROW); RegisterClassEx(&wc); hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,ClassName,AppName,WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,300,200,NULL,NULL,hInstance,NULL); ShowWindow(hWnd,SW_SHOWNORMAL); UpdateWindow(hWnd); while(GetMessage(&msg,NULL,0,0) TranslateMessage(&msg); DispatchMessage(&msg); return msg.wParam;分析: hwndEdit = CreateWindowEx(NULL,EditClass,NULL,WS_VISIBLE|WS_CHILD|ES_LEFT|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL,0,0,0,0,hWnd,(HMENU)EditID, g_hInstance,NULL); 处理 WM_CREATE消息时,我们创建一个编辑控件。请注意,我们把该控件大小的有关参数都设成0,因为我们稍后将重新设置该编辑控件的大小,使得其覆盖父窗口的整个客户区。注意:本例中我们没有必要调用ShowWindow来显示编辑控件,因为在创建时在其风格中已设置了WS_VISIBLE标志位,在创建父窗口时也可以使用这个小技巧。;= ; Initialize the members of OPENFILENAME structure ;= g_ofn.lStructSize = sizeof(g_ofn); g_ofn.hwndOwner = hWnd; g_ofn.hInstance = g_hInstance; g_ofn.lpstrFilter = FilterString; g_ofn.lpstrFile = buffer; g_ofn.nMaxFile = MAXSIZE;创建完编辑控件后,我们初始话g_ofn变量的成员。因为稍后在保存文件时还要使用该结构体变量,所以此处只初始化要用到的公共部分。WM_CREATE 消息的处理部分是进行这种初始化的绝佳之处。 case WM_SIZE: MoveWindow(hwndEdit,0,0,LOWORD(lParam),HIWORD(lParam),TRUE); break;当主窗口的客户区部分大小改变时,我们的应用程序将接收到WM_SIZE 消息。当然该窗口第一次显示时,我们也将接收到该消息。要接收到该消息,主窗口必须有CS_VREDRAW和CS_HREDRAW风格。我们应该把缩放编辑控件的动作放到此处。我们要把编辑控件变成和我们的窗口客户区一样大,所以先得要得到父窗口客户区的大小。这些值包含在参数lParam中,lParam的高字部分是客户区的高,底字部分是客户区的宽。然后我们调用MoveWindow函数来重新调整编辑控件的大小,该函数不仅能够移动窗口的位置,而且能够改变窗口的大小。 if(LOWORD(wParam) = IDM_OPEN) g_ofn.Flags = OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST |OFN_LONGNAMES|OFN_EXPLORER|OFN_HIDEREADONLY; if(GetOpenFileName(&g_ofn) 当用户选择了File/Open菜单项时,我们填充ofn的其他成员,然后调用GetOpenFileName函数显示一个“打开文件”对话框。 hFile = CreateFile(buffer,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE,NULL);如果用户选择了一个文件时,我们调用CreateFile函数来打开。我们设置标志位来让该函数的文件能够读写。文件打开后我们把返回的文件句柄保存在一个全局变量中以便以后使用。CreateFile函数应用非常广泛,其原型如下:HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);dwDesiredAccess 指定想要进行的操作。 0 打开文件查询它的属性。 GENERIC_READ 打开文件读 GENERIC_WRITE 打开文件写. dwShareMode 指定文件的共享模式。 0 不让其他进程共享,即当您打开该文件后,其他进程欲打开该文件时将失败。 FILE_SHARE_READ 允许其他进程读。 FILE_SHARE_WRITE 允许其他进程写。 lpSecurityAttributes 该属性在WIN95下无效。 dwCreationDistribution 指定欲生成的文件在其已存在和未存在时应做的动作。 CREATE_NEW 生成一个新文件。如果文件已存在则失败。 CREATE_ALWAYS 无论文件是否存在都生成一个新文件。 OPEN_EXISTING 打开存在的文件。如果文件不存在则失败。 OPEN_ALWAYS 打开文件,如果该文件不存在则生成,这和在dwCreationDistribution 中设置 CREATE_NEW标志位一样。 TRUNCATE_EXISTING打开文件。打开时该文件的长度裁减到零(也即完全不要原来的文件了)。这要求调用进程必须有GENERIC_WRITE的权利,如果指定的文件不存在,该函数返回失败。 dwFlagsAndAttributes 指定文件的属性。 FILE_ATTRIBUTE_ARCHIVE 该文件具有一般的归档文件的属性。用户可以用该标志位来标记文件的删除和备份。 FILE_ATTRIBUTE_COMPRESSED 文件或目录是压缩的。对于文件来说是压缩其中的所有数据,而对于目录来说新生成的子目录和文件都要压缩。 FILE_ATTRIBUTE_NORMAL 该文件没有一般的属性集。该标志位只能单独使用。 FILE_ATTRIBUTE_HIDDEN 该文件是隐藏文件,当浏览一般的文件目录时将不显示它。 FILE_ATTRIBUTE_READONLY 该文件是只读文件。应用程序可以读其中的内容,但不可以写。 FILE_ATTRIBUTE_SYSTEM 该文件是系统文件。 hMemory = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,MEMSIZE); pMemory = GlobalLock(hMemory); 文件打开后,我们将分配一块内存供随后的API 函数ReadFile 和 WriteFile使用。我们使用标志GMEM_MOVEABLE来使得WINDOWS总是把内存块移到可靠的内存中去,GMEM_ZEROINIT告诉WINDOWS把刚刚分配的内存置为零。如果GlobalAlloc调用成功的话,会返回内存块的句柄,我们把该句柄传给GlobalLock函数以得到指向内存块的指针。 ReadFile(hFile,pMemory,MEMSIZE-1,&SizeReadWrite,NULL); SendMessage(hwndEdit,WM_SETTEXT,NULL,(LPARAM)pMemory);使内存块可用后,我们调用ReadFile函数从文件中读数据。对于第一次打开的文件,文件的指针放在偏移0处,像本例中我们从偏移0处往前读。ReadFile的第一个参数是文件句柄,第二个参数是指向内存块的指针,接下来的参数是要读的数据的长度,第四个参数是一个指向DWORD型的参数的指针,它用来存放实际读的数据的长度。读完了后,我们把这些内容存放到编辑控件中,这要用消息

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论