Win32彙編教程八 圖形介面的操作 (轉)
--------------------------------------------------------------------------------
有關GDI和點陣圖
GDI 即圖形裝置介面,是 最重要的部分之一,它大部分由 GDI32.DLL 庫中的 來處理,GDI 的主要目的之一是支援與裝置無關的圖形,對於 D下的圖形程式設計,很多人可能“心有餘悸”,因為PC 中有太多種類的顯示卡,而幾乎每個顯示卡的處理都是不同的,即使後來有了 Vesa 程式設計,我們還是不能全部撇開具體的,Windows GDI 使我們對圖形的程式設計變得相對簡單了很多,由於GDI 是 Windows 最龐大的部分,並不是幾句話能講清楚的,本節要講的是 Windows 下GDI 的基本處理步驟和簡單的點陣圖處理,並沒有涉及到 一類的程式設計。只希望能對朋友們有所啟發。
Windows 並不允許員訪問顯示硬體,它的所有對螢幕的操作是透過環境裝置(DC)來處理的,螢幕上的每一個視窗對應一個DC,你可以把一個DC 想象成這個視窗的影片緩衝區,你對DC的操作結果會反映到螢幕上,在視窗的DC之外,你也可以自己建立DC,這相當於建立一箇中的緩衝區,你對這個DC的操作結果儲存在記憶體中。你也可以用 API 在不同的DC之間複製資料,比如說你可以在記憶體DC 中先建立好資料,然後複製到視窗的DC中,就相當於完成了螢幕的重新整理。
與DC的取得、建立取消有關的API有以下幾種:
GetDC(hWnd) - 取得某個視窗的DC,API 返回對應的 DC 控制程式碼
ReleaseDC(hWnd,hDC) - 釋放用 GetDC 取得的 DC 控制程式碼
CreateCompatibleDC(hDC) - 從一個已知的 DC 控制程式碼中建立一個記憶體 DC,各種引數、屬性參考已知的 DC
DeleteDC(hDC) - 刪除用CreateCompatibleDC 建立的 DC
上面的4個API,必須成對出現,用 GetDC 取得的DC 必須用 ReleaseDC 釋放,而用 CreateCompatibleDC 建立的 DC 必須用 DeleteDC 刪除,不能混淆。DC 的作用範圍:用 GetDC 取得的視窗 DC 必須儘快釋放,你不應該在 Windows 的不同訊息之間儲存 DC 控制程式碼,而用 CreateCompatibleDC 建立的 DC 可以長期儲存,舉例說明,如果你在 WM_PAINT 和 WM_SIZE 訊息中都要對視窗的 DC 進行操作,你不能在 WM_INIT 時先 GetDC,然後儲存控制程式碼,最後在 WM_CLOSE 訊息時 ReleaseDC,而是必須在 WM_PAINT 和 WM_SIZE 開始的地方 GetDC,在訊息結束的地方就 ReleaseDC,而用 CreateCompatibleDC 建立的則相反,你可以在 WM_INIT 時建立,在 WM_CLOSE 時刪除。
如果想把一個點陣圖畫到 DC 中,你只需簡單的用 invoke ,hDc,hBitmap 就行了,是不是很簡單?但圖形操作並不是單單把點陣圖放入螢幕就行了,還要涉及到位的操作,如把前景點陣圖的邊緣去掉貼入背景點陣圖等。 Windows 的 GDI 提供了下面一些 DC 間的複製 API,中間就包括了複製的:
BitBlt hDcDest,XDest,YDest,Width,Height,hDc,XSrc,YSrc,dwRop
這個 API 把 hDcSource 的 XSrc,YSrc 座標處的內容複製到 hDcDest 的 XDest,YDest 處,複製大小為 Width,Height。
PatBlt hDc,X,Y,Width,Height,dwRop 是用預定義的刷子等 Object 填充 DC
StretchBlt,hDcDest,XDest,YDest,Width,Height,hDcSource,XSrc,YSrc,WidthSrc,HeightSrc,dwRop 是複製並自動縮放大小,你可以注意到它和 BitBlt 相比多了兩個引數 WidthSrc 和 HeightSrc,別的都是一樣的。
以上API 中的 dwRop 引數是最關鍵的,它的值有 SRCCOPY,SRCPAINT,SRCAND,DSTINVERT 等,表示源DC 複製到目標DC後象素的計算方法,SRCCOPY 表示用源DC覆蓋目標DC,SRCPAINT是 OR 操作,SRCAND 是執行 AND 操作,DSTINVERT 是取反,舉例說明,如果源DC中的某一點是黑色,目標DC對應的點是紅色,那麼用 SRCCOPY後,目標DC的點變成黑色,用SRCPAINT 後還是紅色,因為黑 (000000) or 紅(0000ff) =紅(0000ff)。
對應一般對螢幕或視窗進行圖形操作的步驟如下。
用GetDC 取得目標視窗的 DC
用 CreateCompatibleDC 建立一個記憶體中的 DC用作緩衝區
用 SelectObject 填充記憶體DC 或別的辦法對記憶體DC進行操作,一句話,先把要顯示的東西處理好
用 BitBlt 把記憶體DC 複製到視窗 DC中,完成螢幕重新整理。
本節的例子程式是一個螢幕放大鏡,它把滑鼠移動到的地方的螢幕內容放大一倍顯示到自己的視窗中。
源程式 - 源
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Programmed by 羅雲彬, bigluo@telekbird.com.cn
; site:
; LuoYunBin's ASM page (羅雲彬的程式設計樂園)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 版本資訊
; 彙編教程附帶源程式 - 螢幕放大器
; V1.0 ------ 2000年7月1日
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none ; case sensitive
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 資料
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
include kernel32.inc
include comctl32.inc
include comdlg32.inc
include gdi32.inc
includelib user32.lib
includelib kernel32.lib
includelib comctl32.lib
includelib comdlg32.lib
includelib gdi32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 資料
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN equ 1000
ID_BITMAP equ 1001
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 資料段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hWinPic dd ?
hDcMem dd ?
hBitmap dd ?
hWinDesktop dd ?
hInstance dd ?
szBuffer 256 dup (?)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 子程式宣告
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain PROTO :D,:DWORD,:DWORD,:DWORD
.data
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 程式碼段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
include Win.asm
;********************************************************************
_ProcDlgMain proc uses ebx edi esi,
hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
local @stPoint:POINT
local @hDcDesktop,@hDcPic
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
invoke KillTimer,hWnd,1
invoke DeleteDC,hDcMem
invoke DeleteObject,hBitmap
; *******************************************************************
.elseif eax == WM_INITDIALOG
invoke GetDlgItem,hWnd,ID_BITMAP
mov hWinPic,eax
invoke GetDesktopWindow
mov hWinDesktop,eax
invoke SetWindowPos,hWnd,HWND_TOPMOST,0,0,0,0,
SWP_NOMOVE or SWP_NOSIZE
; *******************************************************************
invoke GetDC,hWinDesktop
mov @hDcDesktop,eax
invoke CreateCompatibleDC,@hDcDesktop
mov hDcMem,eax
invoke CreateCompatibleBitmap,@hDcDesktop,80,80
mov hBitmap,eax
invoke SelectObject,hDcMem,hBitmap
invoke ReleaseDC,hWinDesktop,@hDcDesktop
invoke SetTimer,hWnd,1,100,NULL
; *******************************************************************
.elseif eax == WM_TIMER
invoke GetCursorPos,addr @stPoint
sub @stPoint.x,20
sub @stPoint.y,20
.if @stPoint.x < 0
mov @stPoint.x,0
.endif
.if @stPoint.y < 0
mov @stPoint.y,0
.endif
invoke GetDC,hWinDesktop
mov @hDcDesktop,eax
invoke GetDC,hWinPic
mov @hDcPic,eax
invoke PatBlt,hDcMem,0,0,80,80,BLACKNESS
invoke StretchBlt,hDcMem,0,0,80,80,
@hDcDesktop,@stPoint.x,@stPoint.y,40,40,SRCCOPY
invoke BitBlt,@hDcPic,0,0,80,80,
hDcMem,0,0,SRCCOPY
invoke ReleaseDC,hWinDesktop,@hDcDesktop
invoke ReleaseDC,hWinPic,@hDcPic
.else
;********************************************************************
; 注意:對話方塊的訊息處理後,要返回 TRUE,對沒有處理的訊息
; 要返回 FALSE
;********************************************************************
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
;********************************************************************
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0
invoke ExitProcess,NULL
end start
程式的分析和要點
在程式的初始化中,我們用GetDc 取的桌面的螢幕的 DC,再用 CreateCompatibleDC 建立一個記憶體DC做緩衝區,建立一個點陣圖再用 SelectObject 把 hDcMem 設定為這個點陣圖是為了是 hDcMem 的大小變為 80x80。
invoke GetDC,hWinDesktop
mov @hDcDesktop,eax
invoke CreateCompatibleDC,@hDcDesktop
mov hDcMem,eax
invoke CreateCompatibleBitmap,@hDcDesktop,80,80
mov hBitmap,eax
invoke SelectObject,hDcMem,hBitmap
invoke ReleaseDC,hWinDesktop,@hDcDesktop
然後在程式的每 0.1 秒一次的 WM_TIMER 定時器訊息中,我們先用 GetDC 取得桌面和對話方塊中文字框的控制程式碼,然後用 PatBlt 把記憶體DC清除為黑色,再用 StretchBlt 從桌面DC中複製 40x40的區域到記憶體 DC 中,新的大小是 80x80(放大功能就是這樣實現的),複製的位置是用 GetCursorPos 取得的,也就是滑鼠的當前位置,最後用 BitBlt 把記憶體DC 複製到對話方塊中。如果直接把桌面DC 複製到對話方塊中也可以,但是當滑鼠移動到螢幕邊緣上時,由於螢幕外的點是無效的,所以對話方塊中的一部分會破圖,大家可以改動程式試試。
invoke GetCursorPos,addr @stPoint
invoke GetDC,hWinDesktop
mov @hDcDesktop,eax
invoke GetDC,hWinPic
mov @hDcPic,eax
invoke PatBlt,hDcMem,0,0,80,80,BLACKNESS
invoke StretchBlt,hDcMem,0,0,80,80,
@hDcDesktop,@stPoint.x,@stPoint.y,40,40,SRCCOPY
invoke BitBlt,@hDcPic,0,0,80,80,
hDcMem,0,0,SRCCOPY
invoke ReleaseDC,hWinDesktop,@hDcDesktop
invoke ReleaseDC,hWinPic,@hDcPic
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-996030/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Win32彙編教程十二 管道操作 (轉)Win32
- 基本概念(win32)彙編教程(轉)Win32
- Win32彙編教程二 Win32彙編程式的結構和語法 (轉)Win32
- Win32彙編教程十 定時器的應用 (轉)Win32定時器
- Win32彙編教程四 編寫一個簡單的視窗 (轉)Win32
- Win32彙編教程七 控制元件的子類化 (轉)Win32控制元件
- Iczelion 的 Win32Asm VxD 彙編教程 (八) (轉)Win32ASM
- Win32彙編的環境和基礎(轉)Win32
- Win32彙編的環境和基礎 (轉)Win32
- Billy Belceb 病毒編寫教程for Win32 ----簡單介紹Win32
- Billy Belceb 病毒編寫教程for Win32 ----Win32優化Win32優化
- Billy Belceb 病毒編寫教程for Win32 ----Win32多型Win32多型
- DirectX圖形介面指南的介紹(轉)
- Win32彙編教程三 一個簡單的對話方塊 --- 兼談資原始檔的使用 (轉)Win32
- Jack's第一個Win32彙編程式HelloWorldWin32
- Jack整理的Win32彙編基礎知識Win32
- win32下彙編程式碼結構學習Win32
- Billy Belceb 病毒編寫教程for Win32 ----Win32 反除錯Win32除錯
- Billy Belceb 病毒編寫教程for Win32 ----高階Win32技術Win32
- Iczelion 的 Win32Asm VxD 彙編教程 (二) (轉)Win32ASM
- Iczelion 的 Win32Asm VxD 彙編教程 (四) (轉)Win32ASM
- Iczelion 的 Win32Asm VxD 彙編教程 (三) (轉)Win32ASM
- Iczelion 的 Win32Asm VxD 彙編教程 (七) (轉)Win32ASM
- Iczelion 的 Win32Asm VxD 彙編教程 (六) (轉)Win32ASM
- Iczelion 的 Win32Asm VxD 彙編教程 (一) (轉)Win32ASM
- Iczelion 的 Win32Asm VxD 彙編教程 (五) (轉)Win32ASM
- Billy Belceb 病毒編寫教程for Win32 ----附錄Win32
- Jack架設WIN32彙編程式的開發環境Win32開發環境
- Win32 SDK登錄檔操作——RegQueryValueEx (轉)Win32
- 彙編跳轉指令
- ARM-GUN彙編簡介
- iOS彙編入門教程(一)ARM64彙編基礎iOS
- canvas圖形編輯器Canvas
- CAD列印圖形教程
- Linux7 圖形介面的切換Linux
- 圖形介面的TCP/IP簡單通訊TCP
- Win32 SDK登錄檔操作——RegOpenKey (轉)Win32Go
- Win32 SDK登錄檔操作——RegCloseKey (轉)Win32GC