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

📄 lion-tutorial25.htm

📁 内有一些代码
💻 HTM
字号:
<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">Tutorial 25: Simple Bitmap</p>
<hr size="1">
<strong> </strong> In this tutorial, we will learn how to use bitmap in our program. 
To be exact, we will learn how to display a bitmap in the client area of our window. 
Download <a href="files/tut25.zip">the example</a>. 
<h3> Theory</h3>
Bitmaps can be thought of as pictures stored in computer. There are many picture 
formats used with computers but Windows only natively supports Windows Bitmap 
Graphics files (.bmp). The bitmaps I'll refer to in this tutorial are Windows 
bitmap graphics files. The easiest way to use a bitmap is to use it as a resource. 
There are two ways to do that. You can include the bitmap in the resource definition 
file (.rc) as follows: <br>
&nbsp; 
<blockquote>#define IDB_MYBITMAP&nbsp;&nbsp; 100 <br>
  IDB_MYBITMAP&nbsp; <b>BITMAP</b>&nbsp; "c:\project\example.bmp"</blockquote>
This method uses a constant to represent the bitmap. The first line just creates 
a constant named IDB_MYBITMAP which has the value of 100. We will use this label 
to refer to the bitmap in the program. The next line declares a bitmap resource. 
It tells the resource compiler where to find the actual bmp file. <br>
The other method uses a name to represent the bitmap as follows: 
<blockquote>MyBitMap&nbsp; <b>BITMAP</b> "c:\project\example.bmp"</blockquote>
This method requires that you refer to the bitmap in your program by the string 
"MyBitMap" instead of a value. <br>
Either method works fine as long as you know which method you're using. <br>
Now that we put the bitmap in the resource file, we can go on with the steps in 
displaying it in the client area of our window. 
<ol>
  <li> call LoadBitmap to get the bitmap handle. LoadBitmap has the following 
    definition:</li>
</ol>
<ol>
  <ol>
    <b>LoadBitmap proto hInstance:HINSTANCE, lpBitmapName:LPSTR</b> 
  </ol>
  <p><br>
    This function returns a bitmap handle. hInstance is the instance handle of 
    our program. lpBitmapName is a pointer to the string that is the name of the 
    bitmap (incase you use the second method to refer to the bitmap). If you use 
    a constant to refer to the bitmap (like IDB_MYBITMAP), you can put its value 
    here. (In the example above it would be 100). A short example is in order: 
  <ol>
    &nbsp; <br>
    First Method: 
    <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>Second Method: 
    <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> Obtain a handle to device context (DC). You can obtain this handle by calling 
    BeginPaint in response to WM_PAINT message or by calling GetDC anywhere.</li>
  <li> Create a memory device context which has the same attribute as the device 
    context we just obtained. The idea here is to create a kind of "hidden" drawing 
    surface which we can draw the bitmap on. When we are finished with the operation, 
    we just copy the content of the hidden drawing surface to the actual device 
    context in one function call. It's an example of double-buffer technique used 
    for fast display of pictures on the screen. You can create this "hidden" drawing 
    surface by calling CreateCompatibleDC.</li>
</ol>
<ol>
  <ol>
    CreateCompatibleDC&nbsp; proto&nbsp; hdc:HDC 
  </ol>
  <p><br>
    If this function succeeds, it returns the handle of the memory device context 
    in eax. hdc is the handle to the device context that you want the memory DC 
    to be compatible with. 
  <li> Now that you got a hidden drawing surface, you can draw on it by selecting 
    the bitmap into it. This is done by calling SelectObject with the handle to 
    the memory DC as the first parameter and the bitmap handle as the second parameter. 
    SelectObject has the following definition:</li>
</ol>
<ol>
  <ol>
    SelectObject&nbsp;&nbsp; proto&nbsp; hdc:HDC, hGdiObject:DWORD 
  </ol>
  <li> The bitmap is drawn on the memory device context now. All we need to do 
    here is to copy it to the actual display device, namely the true device context. 
    There are several functions that can perform this operation such as BitBlt 
    and StretchBlt. BitBlt just copies the content of one DC to another so it's 
    fast while StretchBlt can stretch or compress the bitmap to fit the output 
    area. We will use BitBlt here for simplicity. BitBlt has the following definition:</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> is the handle of the device context that serves as the destination 
  of bitmap transfer operation <br>
  <b>nxDest, nyDest </b>are the coordinate of the upper left corner of the output 
  area <br>
  <b>nWidth, nHeight </b>are the width and height of the output area <br>
  <b>hdcSrc </b>is the handle of the device context that serves as the source 
  of bitmap transfer operation <br>
  <b>nxSrc, nySrc </b>are the coordinate of the upper left corner of the source 
  rectangle. <br>
  <b>dwROP </b>is the raster-operation code (hence the acronym ROP) that governs 
  how to combine the color data of the bitmap to the existing color data on the 
  output area to achieve the final result. Most of the time, you only want to 
  overwrite the existing color data with the new one. 
  <li> When you're done with the bitmap, delete it with DeleteObject API call.</li>
</ol>
That's it! To recapitulate, you need to put the bitmap into the resource scipt. 
Then load it from the resource with LoadBitmap. You'll get the bitmap handle. 
Next you obtain the handle to the device context of the area you want to paint 
the bitmap on. Then you create a memory device context that is compatible with 
the device context you just obtained. Select the bitmap into the memory DC then 
copy the content of the memory DC to the real DC. 
<h3> Example Code:</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; 
  The resource script  <br>
   ;---------------------------------------------------------------------  
  <br>
  <b> #define IDB_MAIN 1 </b> <br>
  <b> IDB_MAIN BITMAP "tweety78.bmp" </b> 
<h3> Analysis:</h3>
There is not much to analyze in this tutorial ;) <br>
&nbsp; 
<blockquote><b> #define IDB_MAIN 1 </b> <br>
  <b> IDB_MAIN BITMAP "tweety78.bmp" </b></blockquote>
<b>Define a constant named IDB_MAIN, assign 1 as its value. And then use that 
constant as the bitmap resource identifier. The bitmap file to be included in 
the resource is "tweety78.bmp" which resides in the same folder as the resource 
script.</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>In response to WM_CREATE, we call LoadBitmap to load the bitmap from the 
  resource, passing the bitmap's resource identifier as the second parameter to 
  the API. We get the handle to the bitmap when the function returns.</b> <br>
  <b>Now that the bitmap is loaded, we can paint it in the client area of our 
  main window.</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>We choose to paint the bitmap in response to WM_PAINT message. We first call 
  BeginPaint to obtain the handle to the device context. Then we create a compatible 
  memory DC with CreateCompatibleDC. Next select the bitmap into the memory DC 
  with SelectObject. Determine the dimension of the client area with GetClientRect. 
  Now we can display the bitmap in the client area by calling BitBlt which copies 
  the bitmap from the memory DC to the real DC. When the painting is done, we 
  have no further need for the memory DC so we delete it with DeleteDC. End painting 
  session with EndPaint. 
<blockquote> &nbsp;.elseif uMsg==WM_DESTROY  <br>
  <b> &nbsp; invoke DeleteObject,hBitmap </b> <br>
   &nbsp; invoke PostQuitMessage,NULL </blockquote>
When we don't need the bitmap anymore, we delete it with DeleteObject 
<hr size="1">
<div align="center"> This article come from Iczelion's asm page, 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 + -