我正在制作一个将白色椭圆移动到窗口中心的程序。我是使用BeginPaint,EndPaint,Ellipse程序完成此操作的。当没有循环时,它工作正常,显示底部的椭圆,但是当我使用一个循环时,它会移动我需要的椭圆而不是停止响应(我想程序不会返回控制) 。如何解决这个问题?我甚至开始做registegrs值的副本。
WM_PAINT:
invoke BeginPaint, hWnd, addr ps ;
mov hdc, eax ;
invoke GetClientRect, hWnd, addr rect; invoke DrawInitialElipse
invoke DrawInitialElipse
步骤:
DrawInitialElipse proc
LOCAL tempEAL:BYTE
LOCAL tempEAX:DWORD
LOCAL tempEDX:DWORD
LOCAL tempECX:DWORD
mov tempEAL, al
mov tempEAX, eax
mov tempEDX, edx
mov tempECX, ecx
finit
fld initialColorStep
fld currentColorDouble
fadd
fst currentColorDouble
fistp dword ptr currentColorInt
mov al, byte ptr [currentColorInt]
mov tempColor, al
mov esi, currentInitialCirclePositionY
.WHILE (esi != ydiv2)
.if stepNumber1==0
mov edi, startY
mov currentInitialCirclePositionY, edi
.else
dec currentInitialCirclePositionY
.endif
inc stepNumber1
mov edi, currentInitialCirclePositionY
sub edi,cnst_10
mov topLeftY, edi
mov edi, startX
sub edi, cnst_5
mov topLeftX, edi
mov edi, currentInitialCirclePositionY
add edi, cnst_10
mov bottomRightY, edi
mov edi, startX
add edi, cnst_5
mov bottomRightX, edi
invoke CreateBrush, 240,240,240
mov initialBrush, edi
invoke SelectObject, hdc, initialBrush
invoke Ellipse, hdc, topLeftX,topLeftY,bottomRightX,bottomRightY; //рисуем другим перо
invoke Sleep, 10
.ENDW
mov al, tempEAL
mov eax,tempEAX
mov edx,tempEDX
mov ecx,tempECX
ret
DrawInitialElipse endp
答案 0 :(得分:4)
您的代码停止响应,因为您在绘图过程中循环,检查ESI
寄存器的更改,但是您没有在每次循环迭代时使用新值更新ESI
。你最终会陷入无休止的循环中。
您不应该在绘图过程中移动椭圆,移动颜色,甚至睡觉。您应该绘制椭圆的当前状态。完全摆脱循环并将椭圆的当前属性(位置,颜色等)保留在绘图过程之外的单独变量中。每次收到WM_PAINT
时,程序都需要使用当前属性值绘制椭圆一次,然后退出(并且不要忘记调用{在退出EndPaint()
之前{1}}。
要实现动画(移动椭圆,移动颜色等),您可以使用计时器(请参阅SetTimer()
)根据需要更新属性值。每次属性值更改时,请调用InvalidateRect()
让操作系统知道椭圆窗口需要新的WM_PAINT
消息。让您的窗口的消息循环决定何时实际向您发送新的WM_PAINT
消息。达到所需的最终结果时停止计时器。
答案 1 :(得分:0)
您遗失EndPaint()
;
我不知道多次选择同一个gdi对象的行为,但如果不建议在完成当前对象时恢复原始对象,这是一个好习惯。
我不在asm中编码,但我认为它应该像这样
invoke SelectObject, hdc, initialBrush
push eax
...
pop eax
invoke SelectObject, hdc, eax