Winapi Win32绘图应用程序
我必须在Windows中编写一个类似paint的程序。我用的是MASM32。一切正常,但当我移动鼠标画图时,它会画一条虚线,而不是实线 请帮我解决这个问题:(我们有其他的想法吗? 谢谢你,很抱歉我的英语不好 附言:看一张图片,看看我的问题Winapi Win32绘图应用程序,winapi,assembly,masm,masm32,Winapi,Assembly,Masm,Masm32,我必须在Windows中编写一个类似paint的程序。我用的是MASM32。一切正常,但当我移动鼠标画图时,它会画一条虚线,而不是实线 请帮我解决这个问题:(我们有其他的想法吗? 谢谢你,很抱歉我的英语不好 附言:看一张图片,看看我的问题 .386 ; use 80386 instruction .model flat,stdcall ; uses flat memory addressing model option casemap:none include C:\masm32\inc
.386 ; use 80386 instruction
.model flat,stdcall ; uses flat memory addressing model
option casemap:none
include C:\masm32\include\windows.inc ; windows.inc have structures and constants
include C:\masm32\include\user32.inc
includelib C:\masm32\lib\user32.lib ; CreateWindowEx, RegisterClassEx,...
include C:\masm32\include\kernel32.inc
includelib C:\masm32\lib\kernel32.lib ; ExitProcess
include C:\masm32\include\masm32.inc
includelib C:\masm32\lib\masm32.lib
include C:\masm32\include\gdi32.inc
includelib C:\masm32\lib\gdi32.lib
.CONST
DRAWING equ 1
WAITING equ 0
.DATA
ClassName db 'SimpleWinClass',0
AppName db 'Paint',0
labelNoti db 'Notification',0
labelClick db 'Start draw!',0
labelRelease db 'Stop draw!',0
labelDrawing db 'Drawing...',0
labelWaiting db 'Waiting.',0
object db '.',0
fontName db 'myfont',0
StaticClassName db 'static',0
X dw 'x',0
Y dw 'y',0
state db WAITING
.DATA?
; HINSTANCE & LPSTR typedef DWORD in windows.inc
; reserve the space for future use
hInstance HINSTANCE ?
CommandLine LPSTR ?
hitpoint POINT <>
; use for create window
wc WNDCLASSEX <?>
msg MSG <?> ; handle message
hwnd HWND ? ; handle window procedure
hwndX HWND ?
hwndY HWND ?
hwndState HWND ?
hdc HDC ?
ps PAINTSTRUCT <?>
font HGDIOBJ ?
hFont HFONT ?
.CODE
start:
; call GetModuleHandle(null)
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms683199(v=vs.85).aspx
push NULL
call GetModuleHandle ; module handle same as instance handle in Win32
mov hInstance, eax ; return an instance to handle in eax
; call GetCommandLine()
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156(v=vs.85).aspx
call GetCommandLine ; no parameters
mov CommandLine, eax ; return a pointer to the command-line for current process
; call WinMain(hInstance, hPrevInstance, CmdLine, CmdShow)
; our main function
push SW_SHOW
push CommandLine
push NULL
push hInstance
call WinMain
; call ExitProcess
push eax
call ExitProcess
; Define WinMain
WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
; Structure in msdn, define in windows.inc
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms633577(v=vs.85).aspx
; Load default icon
push IDI_APPLICATION
push NULL
call LoadIcon
mov wc.hIcon, eax
mov wc.hIconSm, eax
; Load default cursor
push IDC_ARROW
push NULL
call LoadCursor
mov wc.hCursor, eax
mov wc.cbSize, SIZEOF WNDCLASSEX ; size of this structure
mov wc.style, CS_HREDRAW or CS_VREDRAW ; style of windows https://msdn.microsoft.com/en-us/library/windows/desktop/ff729176(v=vs.85).aspx
mov wc.lpfnWndProc, OFFSET WndProc ; andress of window procedure
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1 ; background color, require to add 1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, OFFSET ClassName
; we register our own class, named in ClassName
push offset wc
call RegisterClassEx
; after register ClassName, we use it to create windows compond
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx
push NULL
push hInstance
push NULL
push NULL
push 600
push 600
push CW_USEDEFAULT
push CW_USEDEFAULT
push WS_OVERLAPPEDWINDOW
push offset AppName
push offset ClassName
push WS_EX_CLIENTEDGE
call CreateWindowEx
mov hwnd, eax ; return windows handle
; display window
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
push CmdShow
push hwnd
call ShowWindow
; update window
; https://msdn.microsoft.com/en-us/library/windows/desktop/dd145167(v=vs.85).aspx
push hwnd
call UpdateWindow
; Message Loop
MESSAGE_LOOP:
; get message
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx
push 0
push 0
push NULL
push offset msg
call GetMessage
; return in eax
; if the function retrieves a message other than WM_QUIT, the return value is nonzero.
; if the function retrieves the WM_QUIT message, the return value is zero.
cmp eax, 0
jle END_LOOP
; translate virtual-key messages into character messages - ASCII in WM_CHAR
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms644955(v=vs.85).aspx
push offset msg
call TranslateMessage
; sends the message data to the window procedure responsible for the specific window the message is for.
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms644934(v=vs.85).aspx
push offset msg
call DispatchMessage
jmp MESSAGE_LOOP
END_LOOP:
mov eax, msg.wParam
ret
WinMain endp
; Handle message with switch(notification)
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
; close app
cmp uMsg, WM_DESTROY
je ON_WM_DESTROY
cmp uMsg, WM_CREATE
je ON_WM_CREATE
cmp uMsg, WM_PAINT
je ON_WM_PAINT
cmp uMsg, WM_LBUTTONDOWN
je ON_WM_LBUTTONDOWN
cmp uMsg, WM_LBUTTONUP
je ON_WM_LBUTTONUP
cmp uMsg, WM_MOUSEMOVE
je ON_WM_MOUSEMOVE
jmp ON_DEFAULT
; user close program
ON_WM_DESTROY:
push NULL
call PostQuitMessage
jmp EXIT
ON_WM_CREATE:
; create static text
push NULL
push hInstance
push 1
push hWnd
push 25
push 50
push 20
push 20
push WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT
push offset X
push offset StaticClassName
push WS_EX_CLIENTEDGE
call CreateWindowEx
mov hwndX, eax
; create static text
push NULL
push hInstance
push 1
push hWnd
push 25
push 50
push 20
push 90
push WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT
push offset Y
push offset StaticClassName
push WS_EX_CLIENTEDGE
call CreateWindowEx
mov hwndY, eax
; create static text
push NULL
push hInstance
push 1
push hWnd
push 25
push 80
push 60
push 20
push WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT
push offset labelWaiting
push offset StaticClassName
push WS_EX_CLIENTEDGE
call CreateWindowEx
mov hwndState, eax
push offset fontName
push DEFAULT_PITCH or FF_DONTCARE
push DEFAULT_QUALITY
push CLIP_DEFAULT_PRECIS
push CLIP_DEFAULT_PRECIS
push DEFAULT_CHARSET
push FALSE
push FALSE
push FALSE
push 700
push 0
push 0
push 16
push 24
call CreateFont
mov font, eax
jmp EXIT
ON_WM_LBUTTONDOWN:
mov [state], DRAWING
push offset labelDrawing
push hwndState
call SetWindowText
jmp EXIT
ON_WM_LBUTTONUP:
mov [state], WAITING
push offset labelWaiting
push hwndState
call SetWindowText
jmp EXIT
ON_WM_MOUSEMOVE:
push lParam
call updateXY
cmp [state], DRAWING
je DRAW
jne EXIT
DRAW:
push FALSE
push NULL
push hWnd
call InvalidateRect
jmp EXIT
ON_WM_PAINT:
push offset ps
push hWnd
call BeginPaint
mov hdc, eax
push font
push hdc
call SelectObject
mov hFont, eax
push 1
push offset object
push hitpoint.y
push hitpoint.x
push hdc
call TextOut
push hFont
push hWnd
call SelectObject
push offset ps
push hWnd
call EndPaint
jmp EXIT
ON_DEFAULT:
; handle any message that program don't handle
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms633572(v=vs.85).aspx
push lParam
push wParam
push uMsg ; message
push hWnd ; windows
call DefWindowProc
jmp EXIT
EXIT:
ret
WndProc endp
updateXY proc lParam:LPARAM
mov eax, lParam
xor ebx, ebx
mov bx, ax
mov hitpoint.x, ebx
push offset X
push ebx
call dwtoa
push offset X
push hwndX
call SetWindowText
mov eax, lParam
shr eax, 16
mov hitpoint.y, eax
push offset Y
push eax
call dwtoa
push offset Y
push hwndY
call SetWindowText
ret
updateXY endp
end start
.386;使用80386指令
.model flat,stdcall;使用平面内存寻址模型
选项案例图:无
include C:\masm32\include\windows.inc;windows.inc具有结构和常量
包括C:\masm32\include\user32.inc
includelib C:\masm32\lib\user32.lib;CreateWindowEx,RegisterClassEx,。。。
包含C:\masm32\include\kernel32.inc
includelib C:\masm32\lib\kernel32.lib;ExitProcess
包括C:\masm32\include\masm32.inc
includelib C:\masm32\lib\masm32.lib
包括C:\masm32\include\gdi32.inc
includelib C:\masm32\lib\gdi32.lib
康斯特先生
图纸equ 1
等待equ 0
.数据
类名数据库“SimpleWinClass”,0
AppName数据库“绘制”,0
labelNoti数据库“通知”,0
labelClick数据库“开始绘制!”,0
labelRelease数据库“停止绘制!”,0
labelDrawing数据库“Drawing…”,0
labelWaiting数据库“正在等待”,0
对象数据库“”,0
fontName数据库“myfont”,0
StaticClassName数据库“静态”,0
X dw'X',0
Y-dw'Y',0
状态数据库等待
.数据?
;windows.inc.中的HINSTANCE和LPSTR typedef DWORD
;保留空间供将来使用
hInstance hInstance?
命令行LPSTR?
生命点
;用于创建窗口
wc WNDCLASSEX
处理消息
hwnd hwnd?;句柄窗口过程
hwndX HWND?
hwndY HWND?
州政府?
hdc hdc?
ps PAINTSTRUCT
字体HGDIOBJ?
哈丰哈丰?
.代码
开始:
;调用GetModuleHandle(null)
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms683199(v=vs.85).aspx
推空
调用GetModuleHandle;模块句柄与Win32中的实例句柄相同
mov hInstance,eax;返回要在eax中处理的实例
;调用GetCommandLine()
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156(v=vs.85).aspx
调用GetCommandLine;无参数
mov命令行,eax;返回指向当前进程的命令行的指针
;调用WinMain(hInstance、HPPreInstance、CmdLine、CmdShow)
;我们的主要职能
推送SW_SHOW
推命令行
推空
推挤站姿
打电话给WinMain
;呼叫出口程序
推送eax
呼叫退出过程
;定义WinMain
WinMain proc hInst:HINSTANCE、hPrevInst:HINSTANCE、CmdLine:LPSTR、CmdShow:DWORD
;msdn中的结构,在windows.inc中定义
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms633577(v=vs.85).aspx
;加载默认图标
推送IDI_应用程序
推空
调用加载图标
莫夫·沃克·希肯,埃克斯
mov wc.hIconSm,eax
;加载默认光标
按箭头
推空
调用LoadCursor
mov wc.hCursor,eax
mov wc.cbSize,WNDCLASSEX的尺寸;此结构的尺寸
mov wc.style、CS_HREDRAW或CS_VREDRAW;窗口样式https://msdn.microsoft.com/en-us/library/windows/desktop/ff729176(v=vs.85).aspx
mov wc.lpfnWndProc,偏移量WndProc;窗口程序的安德鲁斯
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,空
推挤站姿
流行语
mov wc.hbrBackground,颜色窗口+1;背景色,需要添加1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,偏移量ClassName
;我们注册我们自己的类,以ClassName命名
推偏wc
调用注册表类
;注册类名后,我们使用它创建windows组件
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx
推空
推挤站姿
推空
推空
推600
推600
按顺时针方向按默认值
按顺时针方向按默认值
按WS_重叠窗口
推送偏移量AppName
推送偏移类名
推送WS_EX_客户
调用CreateWindowEx
mov hwnd,eax;返回窗口句柄
;显示窗口
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
推送CmdShow
推送
呼叫显示窗口
;更新窗口
; https://msdn.microsoft.com/en-us/library/windows/desktop/dd145167(v=vs.85).aspx
推送
调用UpdateWindow
;消息循环
消息循环:
;得到消息
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx
推0
推0
推空
推送偏移量消息
调用GetMessage
;返回eax
;如果函数检索到WM_QUIT以外的消息,则返回值为非零。
;如果函数检索WM_QUIT消息,则返回值为零。
cmp-eax,0
端环
;将虚拟密钥消息转换为字符消息-WM_CHAR中的ASCII
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms644955(v=vs.85).aspx
推送偏移量消息
呼叫翻译消息
;将消息数据发送到负责消息所针对的特定窗口的窗口过程。
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms644934(v=vs.85).aspx
推送偏移量消息
呼叫调度消息
jmp消息循环
结束循环:
mov eax,msg.wParam
ret
WinMain endp
;使用开关处理消息(通知)
; https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx
WndProc hWnd:hWnd,uMsg:UINT,wParam:wParam,lParam:lParam
;关闭应用程序
cmp uMsg,WM_销毁
我在毁灭
cmp uMsg,WM_创建
我在创造
cmp uMsg,WM_油漆
我在油漆上
cmp uMsg,WM_LBUTTONDOWN
object db ' ',0
...
ON_WM_PAINT:
...
mov hFont, eax
invoke SetBkColor, hdc, 00FF0000h
push 1
push offset object
push hitpoint.y
push hitpoint.x
push hdc
call TextOut
...
push 1
push offset object
push hitpoint.y
push hitpoint.x
push hdc
call TextOut
invoke TextOut, hdc, hitpoint.x, hitpoint.y, offset object, 1
push offset fontName
push DEFAULT_PITCH or FF_DONTCARE
push DEFAULT_QUALITY
push CLIP_DEFAULT_PRECIS
push CLIP_DEFAULT_PRECIS
push DEFAULT_CHARSET
push FALSE
push FALSE
push FALSE
push 700
push 0
push 0
push 18 ; Width
push 12 ; Height
call CreateFont
mov font, eax
.386 ; use 80386 instruction
.model flat,stdcall ; uses flat memory addressing model % STDCALL as default calling convention
option casemap:none
include C:\masm32\include\windows.inc
include C:\masm32\include\kernel32.inc
include C:\masm32\include\user32.inc
include C:\masm32\include\gdi32.inc
include C:\masm32\include\masm32.inc
includelib C:\masm32\lib\kernel32.lib ; ExitProcess, GetCommandLineA, GetModuleHandleA
includelib C:\masm32\lib\user32.lib ; BeginPaint, CreateWindowExA@, DefWindowProcA, DispatchMessageA, EndPaint, GetMessageA, InvalidateRect, LoadCursorA, LoadIconA, PostQuitMessage, RegisterClassExA, SetWindowTextA, ShowWindow, TranslateMessage, UpdateWindow
includelib C:\masm32\lib\gdi32.lib ; CreatePen, LineTo, MoveToEx, SelectObject
includelib C:\masm32\lib\masm32.lib ; dwtoa
.CONST
DRAWING equ 1
WAITING equ 0
.DATA
ClassName db 'SimpleWinClass',0
AppName db 'Paint',0
labelDrawing db 'Drawing...',0
labelWaiting db 'Waiting.',0
StaticClassName db 'static',0
X dw 'x',0
Y dw 'y',0
state db WAITING
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hitpoint POINT <>
lastpoint POINT <>
wc WNDCLASSEX <?>
msg MSG <?> ; handle message
hwnd HWND ? ; handle window procedure
hwndX HWND ?
hwndY HWND ?
hwndState HWND ?
hdc HDC ?
ps PAINTSTRUCT <?>
hPen HPEN ?
.CODE
updateXY PROC lParam:LPARAM
movzx eax, WORD PTR lParam
mov hitpoint.x, eax
invoke dwtoa, eax, offset X
invoke SetWindowText, hwndX, offset X
mov eax, lParam
shr eax, 16
mov hitpoint.y, eax
invoke dwtoa, eax, offset Y
invoke SetWindowText, hwndY, offset Y
ret
updateXY ENDP
; https://msdn.microsoft.com/library/windows/desktop/ms633573.aspx
WndProc PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
cmp uMsg, WM_MOUSEMOVE
je ON_WM_MOUSEMOVE
cmp uMsg, WM_PAINT
je ON_WM_PAINT
cmp uMsg, WM_CREATE
je ON_WM_CREATE
cmp uMsg, WM_LBUTTONDOWN
je ON_WM_LBUTTONDOWN
cmp uMsg, WM_LBUTTONUP
je ON_WM_LBUTTONUP
cmp uMsg, WM_DESTROY
je ON_WM_DESTROY
jmp ON_DEFAULT
ON_WM_DESTROY: ; User closes program
invoke PostQuitMessage, NULL
jmp EXIT
ON_WM_CREATE:
; Create windows for text
invoke CreateWindowEx, WS_EX_CLIENTEDGE, offset StaticClassName, offset X, WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT, 20, 20, 50, 25, hWnd, 1, hInstance, NULL
mov hwndX, eax
invoke CreateWindowEx, WS_EX_CLIENTEDGE, offset StaticClassName, offset Y, WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT, 90, 20, 50, 25, hWnd, 1, hInstance, NULL
mov hwndY, eax
invoke CreateWindowEx, WS_EX_CLIENTEDGE, offset StaticClassName, offset labelWaiting, WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT, 20, 60, 80, 23, hWnd, 1, hInstance, NULL
mov hwndState, eax
; Create pen for LineTo
invoke CreatePen, PS_SOLID, 10, 00FF0000h
mov hPen, eax
jmp EXIT
ON_WM_LBUTTONDOWN:
; last mouse position = current mouse position
mov eax, hitpoint.x
mov lastpoint.x, eax
mov eax, hitpoint.y
mov lastpoint.y, eax
mov [state], DRAWING
invoke SetWindowText, hwndState, offset labelDrawing
jmp EXIT
ON_WM_LBUTTONUP:
mov [state], WAITING
invoke SetWindowText, hwndState, offset labelWaiting
jmp EXIT
ON_WM_MOUSEMOVE:
invoke updateXY, lParam ; PROC above
cmp [state], DRAWING
jne EXIT
invoke InvalidateRect, hWnd, NULL, FALSE ; https://msdn.microsoft.com/library/dd145002.aspx
jmp EXIT
ON_WM_PAINT:
invoke BeginPaint, hWnd, offset ps
invoke MoveToEx, ps.hdc, lastpoint.x, lastpoint.y, NULL
invoke SelectObject, ps.hdc, hPen;
invoke LineTo, ps.hdc, hitpoint.x, hitpoint.y
mov eax, hitpoint.x ; last mouse position = current mouse position
mov lastpoint.x, eax
mov eax, hitpoint.y
mov lastpoint.y, eax
invoke EndPaint, hWnd, offset ps
jmp EXIT
ON_DEFAULT: ; handle any message that program don't handle
invoke DefWindowProc, hWnd, uMsg, wParam, lParam ; https://msdn.microsoft.com/library/windows/desktop/ms633572.aspx
jmp EXIT
EXIT:
ret
WndProc ENDP
WinMain PROC hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
; WNDCLASSEX structure in MSDN, declaration in windows.inc
; https://msdn.microsoft.com/library/windows/desktop/ms633577.aspx
invoke LoadIcon, NULL, IDI_APPLICATION ; Load default icon
mov wc.hIcon, eax
mov wc.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW ; Load default cursor
mov wc.hCursor, eax
mov wc.cbSize, SIZEOF WNDCLASSEX ; size of this structure
mov wc.style, CS_HREDRAW or CS_VREDRAW ; style of windows https://msdn.microsoft.com/library/windows/desktop/ff729176.aspx
mov wc.lpfnWndProc, OFFSET WndProc ; andress of window procedure
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1 ; background color, require to add 1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, OFFSET ClassName
invoke RegisterClassEx, offset wc ; https://msdn.microsoft.com/library/windows/desktop/ms633587.aspx
; https://msdn.microsoft.com/library/windows/desktop/ms632680.aspx
invoke CreateWindowEx, WS_EX_CLIENTEDGE, offset ClassName, offset AppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 600, 600, NULL, NULL, hInstance, NULL
mov hwnd, eax ; Store windows handle
invoke ShowWindow, hwnd, CmdShow ; https://msdn.microsoft.com/library/windows/desktop/ms633548.aspx
invoke UpdateWindow, hwnd ; https://msdn.microsoft.com/library/windows/desktop/dd145167.aspx
; Message Loop
MESSAGE_LOOP: ; https://msdn.microsoft.com/library/windows/desktop/ms644936.aspx
invoke GetMessage, offset msg, NULL, 0, 0
test eax, eax
jle END_LOOP
invoke TranslateMessage, offset msg
invoke DispatchMessage, offset msg
jmp MESSAGE_LOOP
END_LOOP:
mov eax, msg.wParam
ret
WinMain ENDP
main PROC
invoke GetModuleHandle, NULL ; https://msdn.microsoft.com/library/windows/desktop/ms683199.aspx
mov hInstance, eax ; return an instance to handle in eax
invoke GetCommandLine ; https://msdn.microsoft.com/library/windows/desktop/ms683156.aspx
mov CommandLine, eax ; return a pointer to the command-line for current process
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOW
invoke ExitProcess, eax
main ENDP
END main