⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lion-tut-c25.htm

📁 内有一些代码
💻 HTM
字号:
<!-- saved from url=(0022)http://internet.e-mail -->
<html>

<head>
<link rel="stylesheet" href="../../asm.css">

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>

<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center"><font color="#0000FF" size="3"><b>第二十五课:位图初步</b></font></p>
<hr size="1">
<strong> </strong> 在这一课,我们将学习怎样在程序中使用位图。 
更准确地说,我们要学习的是怎样在一个窗口的客户区中显示位图。 
<h3> 理论</h3>
位图就是存贮于电脑中的图片。位图文件有相当多的格式(译者:如.BMP.JPG.GIF.PIC 等)但Windows仅
支持 Windows Bitmap Graphics 格式,即BMP文件。 本课所指的位图也是BMP文件。 
使用位图最简单的方法就是把它定义在资源文件(.rc)中。 
定义的方法有两种。第一种方法是把它定义为整数宏,具体如下:<br>
&nbsp; 
<blockquote>#define IDB_MYBITMAP&nbsp;&nbsp; 100 <br>
  IDB_MYBITMAP&nbsp; <b>BITMAP</b>&nbsp; "c:\project\example.bmp"</blockquote>
第一行我们定义了一个值为100的整数宏。 第二行我们把这个整数宏指向所要定义的位图, 
这样,编译器就能知道位图所在的路径。<br>
另一种方法是给它起一个名字,也就是把它定义为字符串,具体如下: 
<blockquote>MyBitMap&nbsp; <b>BITMAP</b> "c:\project\example.bmp"</blockquote>
两种方法效果是一样的。
选择哪一种方法,视乎在程序中你喜欢用整数宏还是用字符串来指向位图。 <br>
现在我们已经把位图定义在资源文件中,下一步就是把它显示在窗口的客户区上。
<ol>
  <li>在程序中,我们使用API函数 LoadBitmap 取得位图句柄。 下面是 LoadBitmap 函数的
    完型:</li>
</ol>
<ol>
  <ol>
    <b>LoadBitmap proto hInstance:HINSTANCE, lpBitmapName:LPSTR</b> 
  </ol>
  <p><br>
    该函数返回一个位图句柄。函数有两个参数,其中 hInstance 是程序句柄。 
    lpBitmapName 是位图名字的指针(适用于第二种定义方法)。如果你使用了第一种 
    定义方法,你可以填入指向位图的值或整数宏 
    (对应上例这个值就是100,整数宏是IDB_MYBITMAP)。下面是简单的例子: 
  <ol>
    &nbsp; <br>
    第一种方法: 
    <p>.386 <br>
      .model flat, stdcall <br>
      ................ <br>
      .const <br>
      IDB_MYBITMAP&nbsp;&nbsp;&nbsp; equ 100 <br>
      ............... <br>
      .data? <br>
      hInstance&nbsp; dd ? <br>
      .............. <br>
      .code <br>
      ............. <br>
      &nbsp;&nbsp;&nbsp; invoke GetModuleHandle,NULL <br>
      &nbsp;&nbsp;&nbsp; mov hInstance,eax <br>
      ............ <br>
      &nbsp;&nbsp;&nbsp; invoke LoadBitmap,hInstance,IDB_MYBITMAP <br>
      ........... 
    <p>第二种方法: 
    <p>.386 <br>
      .model flat, stdcall <br>
      ................ <br>
      .data <br>
      BitmapName&nbsp; db "MyBitMap",0 <br>
      ............... <br>
      .data? <br>
      hInstance&nbsp; dd ? <br>
      .............. <br>
      .code <br>
      ............. <br>
      &nbsp;&nbsp;&nbsp; invoke GetModuleHandle,NULL <br>
      &nbsp;&nbsp;&nbsp; mov hInstance,eax <br>
      ............ <br>
      &nbsp;&nbsp;&nbsp; invoke LoadBitmap,hInstance,addr BitmapName <br>
      ...........
  </ol>
  <li> 获得一个设备文本(DC)句柄。你可以在响应WM_PAINT消息时通过API函数BeginPaint获得。
  如果在其它消息中则可以用API函数GetDC获得。</li>
  <li> 创建这个DC的内存映像。这样做的目的是建立一张“隐藏的画纸”,把位图
  “画”在上面,作缓冲之用。完成这项工作后,我们就通过一个函数把“画纸”上的位图复制 
   到真正的DC中。这就是在屏幕上快速显示图象的双缓冲技术。(译者:可以减少图象抖动)
   这张“画纸”用API函数 CreateCompatibleDC 建立,下面是它的完型:</li>
</ol>
<ol>
  <ol>
    CreateCompatibleDC&nbsp; proto&nbsp; hdc:HDC 
  </ol>
  <p><br>
   如果函数执行成功,将返回DC内存映像也即“画纸”的句柄。
  <li>现在我们已经有了“画纸”,可以把位图画在上面了。这可以通过API函数 SelectObject 完成,  
      其中第一个参数是“画纸”的句柄,第二个参数则是位图的句柄,下面是函数的完型:</li>
</ol>
<ol>
  <ol>
    SelectObject&nbsp;&nbsp; proto&nbsp; hdc:HDC, hGdiObject:DWORD 
  </ol>
  <li> 现在位图已经画在“画纸”上了。下一步我们要把位图复制到真正的DC中。 
     有很多API函数都能完成这项工作,例如 BitBlt 和 StretchBlt。
     函数 BitBlt 仅仅将一个DC的内容简单地复制到另一个DC中,而函数 StretchBlt 
     则能够自动调整源DC复制内容的大小已适应目的DC的输出区域大小,因此前者比后者速度更快。
     在这里我们只使用函数 BitBlt ,下面是它的完型: </li>
</ol>
<ol>
  <ol>
    BitBlt&nbsp; proto&nbsp; hdcDest:DWORD, nxDest:DWORD, nyDest:DWORD, nWidth:DWORD, 
    nHeight:DWORD, hdcSrc:DWORD, nxSrc:DWORD, nySrc:DWORD, dwROP:DWORD <br>
    &nbsp; 
  </ol>
  <b>hdcDest</b> 目的DC的句柄。 <br>
  <b>nxDest, nyDest </b>目的DC输出区域的左上角坐标。<br>
  <b>nWidth, nHeight </b> 目的DC输出区域的长和宽。<br>
  <b>hdcSrc </b> 源DC的句柄。<br>
  <b>nxSrc, nySrc </b>源DC中所要复制区域的左上角坐标。 <br>
  <b>dwROP </b>屏面运算码(ROP)。该参数用以确定复制内容的颜色与输出区域原来的颜色按哪种运算
  方式处理。通常,只需要简单地用复制内容把输出区域覆盖掉。
  <li> 一切办妥后,就用API函数 DeleteObject 释放位图对象,也就是把位图“抹掉”。</li>
</ol>
大功告成! 现在再来回顾一下整个过程:首先,你需要把位图定义在资源文件中。 
然后,你需要在程序中载入位图资源,并取得位图句柄。随后,你需要获得位图输出区域的DC,
以及创建这个DC的内存映像,并把位图放进这个DC内存映像中。最后把位图从DC内存映像复制到
真正的DC中。
<h3> 例子:</h3>
 .386  <br>
 .model flat,stdcall  <br>
 option casemap:none  <br>
 include \masm32\include\windows.inc  <br>
 include \masm32\include\user32.inc  <br>
 include \masm32\include\kernel32.inc  <br>
 include \masm32\include\gdi32.inc  <br>
 includelib \masm32\lib\user32.lib  <br>
 includelib \masm32\lib\kernel32.lib  <br>
 includelib \masm32\lib\gdi32.lib  
<p> WinMain proto :DWORD,:DWORD,:DWORD,:DWORD  <br>
  <b> IDB_MAIN&nbsp;&nbsp; equ 1 </b> 
<p> .data  <br>
   ClassName db "SimpleWin32ASMBitmapClass",0  <br>
   AppName&nbsp; db "Win32ASM Simple Bitmap Example",0  
<p> .data?  <br>
   hInstance HINSTANCE ?  <br>
   CommandLine LPSTR ?  <br>
   hBitmap dd ?  
<p> .code  <br>
   start:  <br>
   &nbsp;invoke GetModuleHandle, NULL  <br>
   &nbsp;mov&nbsp;&nbsp;&nbsp; hInstance,eax  <br>
   &nbsp;invoke GetCommandLine  <br>
   &nbsp;mov&nbsp;&nbsp;&nbsp; CommandLine,eax  <br>
   &nbsp;invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT  <br>
   &nbsp;invoke ExitProcess,eax  
<p> WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD  
  <br>
   &nbsp;LOCAL wc:WNDCLASSEX  <br>
   &nbsp;LOCAL msg:MSG  <br>
   &nbsp;LOCAL hwnd:HWND  <br>
   &nbsp;mov&nbsp;&nbsp; wc.cbSize,SIZEOF WNDCLASSEX  <br>
   &nbsp;mov&nbsp;&nbsp; wc.style, CS_HREDRAW or CS_VREDRAW  <br>
   &nbsp;mov&nbsp;&nbsp; wc.lpfnWndProc, OFFSET WndProc  <br>
   &nbsp;mov&nbsp;&nbsp; wc.cbClsExtra,NULL  <br>
   &nbsp;mov&nbsp;&nbsp; wc.cbWndExtra,NULL  <br>
   &nbsp;push&nbsp; hInstance  <br>
   &nbsp;pop&nbsp;&nbsp; wc.hInstance  <br>
   &nbsp;mov&nbsp;&nbsp; wc.hbrBackground,COLOR_WINDOW+1  <br>
   &nbsp;mov&nbsp;&nbsp; wc.lpszMenuName,NULL  <br>
   &nbsp;mov&nbsp;&nbsp; wc.lpszClassName,OFFSET ClassName  <br>
   &nbsp;invoke LoadIcon,NULL,IDI_APPLICATION  <br>
   &nbsp;mov&nbsp;&nbsp; wc.hIcon,eax  <br>
   &nbsp;mov&nbsp;&nbsp; wc.hIconSm,eax  <br>
   &nbsp;invoke LoadCursor,NULL,IDC_ARROW  <br>
   &nbsp;mov&nbsp;&nbsp; wc.hCursor,eax  <br>
   &nbsp;invoke RegisterClassEx, addr wc  <br>
   &nbsp;INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\  <br>
   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\  
  <br>
   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\  
  <br>
   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hInst,NULL  
  <br>
   &nbsp;mov&nbsp;&nbsp; hwnd,eax  <br>
   &nbsp;invoke ShowWindow, hwnd,SW_SHOWNORMAL  <br>
   &nbsp;invoke UpdateWindow, hwnd  <br>
   &nbsp;.while TRUE  <br>
   &nbsp; invoke GetMessage, ADDR msg,NULL,0,0  <br>
   &nbsp; .break .if (!eax)  <br>
   &nbsp; invoke TranslateMessage, ADDR msg  <br>
   &nbsp; invoke DispatchMessage, ADDR msg  <br>
   &nbsp;.endw  <br>
   &nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; eax,msg.wParam  <br>
   &nbsp;ret  <br>
   WinMain endp  
<p> WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM  <br>
   &nbsp;&nbsp; LOCAL ps:PAINTSTRUCT  <br>
   &nbsp;&nbsp; LOCAL hdc:HDC  <br>
   &nbsp;&nbsp; LOCAL hMemDC:HDC  <br>
   &nbsp;&nbsp; LOCAL rect:RECT  <br>
   &nbsp;&nbsp; .if uMsg==WM_CREATE  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke LoadBitmap,hInstance,IDB_MAIN </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov hBitmap,eax </b> <br>
   &nbsp;&nbsp; .elseif uMsg==WM_PAINT  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke BeginPaint,hWnd,addr ps </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hdc,eax </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke CreateCompatibleDC,hdc </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hMemDC,eax </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke SelectObject,hMemDC,hBitmap </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke GetClientRect,hWnd,addr rect </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke BitBlt,hdc,0,0,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke DeleteDC,hMemDC </b> <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke EndPaint,hWnd,addr ps </b> 
  <br>
   &nbsp;.elseif uMsg==WM_DESTROY  <br>
  <b> &nbsp; invoke DeleteObject,hBitmap </b> <br>
   &nbsp; invoke PostQuitMessage,NULL  <br>
   &nbsp;.ELSE  <br>
   &nbsp; invoke DefWindowProc,hWnd,uMsg,wParam,lParam  <br>
   &nbsp; ret  <br>
   &nbsp;.ENDIF  <br>
   &nbsp;xor eax,eax  <br>
   &nbsp;ret  <br>
   WndProc endp  <br>
   end start  
<p> ;---------------------------------------------------------------------  
  <br>
   ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  资源定义<br>
   ;---------------------------------------------------------------------  
  <br>
  <b> #define IDB_MAIN 1 </b> <br>
  <b> IDB_MAIN BITMAP "tweety78.bmp" </b> 
<h3>分析:</h3>
<br> 
<blockquote><b> #define IDB_MAIN 1 </b> <br>
  <b> IDB_MAIN BITMAP "tweety78.bmp" </b></blockquote>
<b>定义整数宏IDB_MAIN的值为1,然后把它指向一个与资源文件处于相同目录文件名为“tweety.bmp"的位图。</b> 
<p> &nbsp;&nbsp; .if uMsg==WM_CREATE  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke LoadBitmap,hInstance,IDB_MAIN </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov hBitmap,eax </b> 
<p><b>在处理 WM_CREATE 消息时, 我们通过API函数 LoadBitmap 载入位图资源,并通过函数
返回值取得位图句柄。</b> <br>
  <b>然后,我们就可以把位图画在窗口客户区上。</b> 
<p> &nbsp;&nbsp; .elseif uMsg==WM_PAINT  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke BeginPaint,hWnd,addr ps </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hdc,eax </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke CreateCompatibleDC,hdc </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hMemDC,eax </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke SelectObject,hMemDC,hBitmap </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke GetClientRect,hWnd,addr rect </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke BitBlt,hdc,0,0,rect.right,rect.bottom,hMemDC,0,0,SRCCOPY </b> 
  <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke DeleteDC,hMemDC </b> <br>
  <b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke EndPaint,hWnd,addr ps </b> 
<p>在本例中,我们选用在响应WM_PAINT消息时画出位图。首先我们通过API函数l 
  BeginPaint 获得窗口客户区的DC句柄。 接着我们通过API函数 CreateCompatibleDC 创建该DC 
  的内存映像,并通过API函数 SelectObject 把位图放进内存映像中。下一步,我们通过API函数 GetClientRect  
  取得窗口客户区的大小。最后,我们通过API函数 BitBlt 把位图从DC内存映像复制到真正的客户区DC中。 
  完成显示工作后,我们通过API函数 DeleteDC 释放DC内存映像,并用API函数 EndPaint 释放客户区DC,
  结束画图工作。 
<blockquote> &nbsp;.elseif uMsg==WM_DESTROY  <br>
  <b> &nbsp; invoke DeleteObject,hBitmap </b> <br>
   &nbsp; invoke PostQuitMessage,NULL </blockquote>
当我们不再需要位图时,通过API函数 DeleteObject 把它释放。 
<hr size="1">
<div align="center"> 翻译:赵昆 Welcom to <a href="http://asm.yeah.net">http://asm.yeah.net</a></div>

</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -