【发布时间】:2017-06-09 11:44:33
【问题描述】:
我必须在 Windows 中编写一个类似于绘图的程序。我正在使用 MASM32。一切正常,但是当我移动鼠标进行绘图时,它会画一条虚线,而不是实线。
请帮我解决这个问题:(我们对此有其他想法吗? 谢谢你,对不起我的英语不好
P/S:看图看看我的问题!
.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
【问题讨论】:
-
有什么理由必须使用汇编语言?
-
这是一个常见问题,您的代码没有任何问题(实际上,恭喜您的结果)。常用的解决方案是从最后一个位置到当前位置绘制的不是点而是线。第一个动作仍然画一个点。
-
鼠标的移动速度可以超过 1px。所以坐标没有创建连续的线。您可以在这些点之间绘制简单的线,甚至可以在短时间内缓存坐标,猜测什么是单笔划,并使用一些双三次/样条插值来获得通过点的软曲线......(对于家庭作业来说可能太复杂了,尤其是在汇编中,简单的线条就足够了)。
-
如果需要画线,请致电MoveToEx和LineTo。无需自己实现线条绘制。如果您需要更高精度的鼠标输入,一个简单的方法是调用GetMouseMovePointsEx。
-
@IInspectable 谢谢它的工作!!!但是如何增加线条的线宽?
标签: winapi assembly masm masm32