📄 lion-tut-c12.htm
字号:
<B>
hInstance,NULL</B> <BR>
<B> mov hwndEdit,eax</B>
<P>处理 WM_CREATE消息时,我们创建一个编辑控件。请注意,我们把该控件大小的有关参数都设成0,因为我们稍后将重新设置该编辑控件的大小,使得其覆盖父窗口的整个客户区。<BR>
注意:本例中我们没有必要调用ShowWindow来显示编辑控件,因为在创建时在其风格中已设置了WS_VISIBLE标志位,在创建父窗口时也可以使用这个小技巧。
<P><B>;==============================================</B> <BR>
<B>; Initialize the members of OPENFILENAME
structure</B> <BR>
<B>;==============================================</B> <BR>
<B> mov ofn.lStructSize,SIZEOF ofn</B>
<BR>
<B> push hWnd</B> <BR>
<B> pop ofn.hWndOwner</B> <BR>
<B> push hInstance</B> <BR>
<B> pop ofn.hInstance</B> <BR>
<B> mov ofn.lpstrFilter, OFFSET
FilterString</B> <BR>
<B> mov ofn.lpstrFile, OFFSET
buffer</B> <BR>
<B> mov ofn.nMaxFile,MAXSIZE</B>
<P>创建完编辑控件后,我们初始话ofn变量的成员。因为稍后在保存文件时还要使用该结构体变量,所以此处只初始化要用到的公共部分。WM_CREATE 消息的处理部分是进行这种初始化的绝佳之处。
<P><B> .ELSEIF uMsg==WM_SIZE</B> <BR>
<B> mov eax,lParam</B> <BR>
<B> mov edx,eax</B> <BR>
<B> shr edx,16</B> <BR>
<B> and eax,0ffffh</B> <BR>
<B> invoke MoveWindow,hwndEdit,0,0,eax,edx,TRUE</B>
<P>当主窗口的客户区部分大小改变时,我们的应用程序将接收到WM_SIZE 消息。当然该窗口第一次显示时,我们也将接收到该消息。要接收到该消息,主窗口必须有CS_VREDRAW和CS_HREDRAW风格。我们应该把缩放编辑控件的动作放到此处。我们要把编辑控件变成和我们的窗口客户区一样大,所以先得要得到父窗口客户区的大小。这些值包含在参数lParam中,lParam的高字部分是客户区的高,底字部分是客户区的宽。然后我们调用MoveWindow函数来重新调整编辑控件的大小,该函数不仅能够移动窗口的位置,而且能够改变窗口的大小。
<P><B> .if ax==IDM_OPEN</B>
<BR>
<B>
mov ofn.Flags, OFN_FILEMUSTEXIST or \</B> <BR>
<B>
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\</B> <BR>
<B>
OFN_EXPLORER or OFN_HIDEREADONLY</B> <BR>
<B>
invoke GetOpenFileName, ADDR ofn</B>
<P>当用户选择了File/Open菜单项时,我们填充ofn的其他成员,然后调用GetOpenFileName函数显示一个“打开文件”对话框。
<P><B>
.if eax==TRUE</B> <BR>
<B>
invoke CreateFile,ADDR buffer,\</B> <BR>
<B>
GENERIC_READ or GENERIC_WRITE ,\</B> <BR>
<B>
FILE_SHARE_READ or FILE_SHARE_WRITE,\</B> <BR>
<B>
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,\</B> <BR>
<B>
NULL</B> <BR>
<B>
mov hFile,eax</B>
<P>如果用户选择了一个文件时,我们调用CreateFile函数来打开。我们设置标志位来让该函数的文件能够读写。文件打开后我们把返回的文件句柄保存在一个全局变量中以便以后使用。CreateFile函数应用非常广泛,其原型如下:
<P><B>CreateFile proto lpFileName:DWORD,\</B> <BR>
<B>
dwDesiredAccess:DWORD,\</B> <BR>
<B>
dwShareMode:DWORD,\</B> <BR>
<B>
lpSecurityAttributes:DWORD,\</B> <BR>
<B>
dwCreationDistribution:DWORD\,</B> <BR>
<B>
dwFlagsAndAttributes:DWORD\,</B> <BR>
<B>
hTemplateFile:DWORD</B>
<P><B>dwDesiredAccess</B> 指定想要进行的操作。
<UL>
<LI><B>0 </B> 打开文件查询它的属性。
<LI><B>GENERIC_READ</B> 打开文件读
<LI><B>GENERIC_WRITE</B> 打开文件写. </LI>
</UL>
<B>dwShareMode</B> 指定文件的共享模式。
<UL>
<LI><B>0</B> 不让其他进程共享,即当您打开该文件后,其他进程欲打开该文件时将失败。
<LI><B>FILE_SHARE_READ</B> 允许其他进程读。
<LI><B>FILE_SHARE_WRITE</B> 允许其他进程写。 </LI>
</UL>
<P><B>lpSecurityAttributes</B> 该属性在WIN95下无效。 <BR>
<B>dwCreationDistribution</B> 指定欲生成的文件在其已存在和未存在时应做的动作。</P>
<UL>
<LI><B>CREATE_NEW</B> 生成一个新文件。如果文件已存在则失败。
<LI><B>CREATE_ALWAYS</B> 无论文件是否存在都生成一个新文件。
<LI><B>OPEN_EXISTING</B> 打开存在的文件。如果文件不存在则失败。
<LI><B>OPEN_ALWAYS</B> 打开文件,如果该文件不存在则生成,这和在dwCreationDistribution 中设置 CREATE_NEW标志位一样。
<LI><B>TRUNCATE_EXISTING</B>打开文件。打开时该文件的长度裁减到零(也即完全不要原来的文件了)。这要求调用进程必须有GENERIC_WRITE的权利,如果指定的文件不存在,该函数返回失败。
</LI>
</UL>
<P>dwFlagsAndAttributes 指定文件的属性。</P>
<UL>
<LI><B>FILE_ATTRIBUTE_ARCHIVE</B> 该文件具有一般的归档文件的属性。用户可以用该标志位来标记文件的删除和备份。
<LI><B>FILE_ATTRIBUTE_COMPRESSED</B> 文件或目录是压缩的。对于文件来说是压缩其中的所有数据,而对于目录来说新生成的子目录和文件都要压缩。
<LI><B>FILE_ATTRIBUTE_NORMAL</B> 该文件没有一般的属性集。该标志位只能单独使用。
<LI><B>FILE_ATTRIBUTE_HIDDEN</B> 该文件是隐藏文件,当浏览一般的文件目录时将不显示它。
<LI><B>FILE_ATTRIBUTE_READONLY</B> 该文件是只读文件。应用程序可以读其中的内容,但不可以写。
<LI><B>FILE_ATTRIBUTE_SYSTEM </B>该文件是系统文件。 </LI>
</UL>
<B>
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE</B> <BR>
<B>
mov hMemory,eax</B> <BR>
<B>
invoke GlobalLock,hMemory</B> <BR>
<B>
mov pMemory,eax</B>
<P>文件打开后,我们将分配一块内存供随后的API 函数ReadFile 和 WriteFile使用。我们使用标志GMEM_MOVEABLE来使得WINDOWS总是把内存块移到可靠的内存中去,GMEM_ZEROINIT告诉WINDOWS把刚刚分配的内存置为零。如果GlobalAlloc调用成功的话,会在eax中返回内存块的句柄,我们把该句柄传给GlobalLock函数以得到指向内存块的指针。
<P><B>
invoke ReadFile,hFile,pMemory,MEMSIZE-1,ADDR SizeReadWrite,NULL</B> <BR>
<B>
invoke SendMessage,hwndEdit,WM_SETTEXT,NULL,pMemory</B>
<P>使内存块可用后,我们调用ReadFile函数从文件中读数据。对于第一次打开的文件,文件的指针放在偏移0处,像本例中我们从偏移0处往前读。ReadFile的第一个参数是文件句柄,第二个参数是指向内存块的指针,接下来的参数是要读的数据的长度,第四个参数是一个指向DWORD型的参数的指针,它用来存放实际读的数据的长度。读完了后,我们把这些内容存放到编辑控件中,这要用消息传递来完成,我们把消息WM_SETTEXT传给编辑控件,其中的参数lParam中包含指向内存块的指针。到此处,编辑控件就可以在它的客户区显示文件的内容了。
<P><B>
invoke CloseHandle,hFile</B> <BR>
<B>
invoke GlobalUnlock,pMemory</B> <BR>
<B>
invoke GlobalFree,hMemory</B> <BR>
<B>
.endif</B>
<P>我们不再需要让文件打开了,因为我们的目的是把修改后的数据保存到另一个文件而不是先前的那一个文件中去。所以我们可以调用CloseHandle来关闭文件。接下来我们解锁内存块,再释放它。实际上我们可以暂不释放内存块,而在以后的操作中重新利用。我们为了演示的原由,选择了释放它。
<P><B>
invoke SetFocus,hwndEdit</B>
<P>当打开文件对话框显示在屏幕上时,输入的焦点切换到了该对话框上。所以在该对话框关闭后,我们必须把焦点切换到编辑控件上。 现在打开文件的阶段结束了,用户可以编辑他们打开的文件了。当用户想把修改后的内容保存到磁盘上时,必须选择File/Save菜单项,这时会显示一个保存文件对话框。显示保存文件对话框其实和打开打开文件对话框基本一样。您甚至可以认为他们的不同只是函数名称不一样而已。此处可以复用大多数ofn变量先前设置的成员的值。
<P><B>
mov ofn.Flags,OFN_LONGNAMES or\</B> <BR>
<B>
OFN_EXPLORER or OFN_HIDEREADONLY</B>
<P>本例中我们将生成一个新文件,所以一定不能有 OFN_FILEMUSTEXIST 和 OFN_PATHMUSTEXIST标志位。dwCreationDistribution
参数应当有CREATE_NEW标志位。 接下来的代码和打开问对话框基本一样。最后调用:
<P><B>
invoke SendMessage,hwndEdit,WM_GETTEXT,MEMSIZE-1,pMemory</B> <BR>
<B>
invoke WriteFile,hFile,pMemory,eax,ADDR SizeReadWrite,NULL</B>
<P>现在我们把修改后的数据从编辑控件中写回内存块,再从内存块写回新文件。
<HR SIZE=1>
<DIV align=center>
<SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/textclick"></SCRIPT>
<BR></DIV><!-- 10:1 文本广告交换 -->
<DIV align=center>
<SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/c21.htm"></SCRIPT>
<!-- 10:1 文本广告交换 --></DIV>
<HR SIZE=1>
<DIV align=center>翻译:Lxx.阿龙,校对:LuoYunBin's Win32 ASM Page, <A
href="http://asm.yeah.net/">http://asm.yeah.net/</A></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -