刚才看这段代码的时候:
procedure TControl.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); begin if CheckNewSize(AWidth, AHeight) and ((ALeft <> FLeft) or (ATop <> FTop) or (AWidth <> FWidth) or (AHeight <> FHeight)) then begin InvalidateControl(Visible, False); FLeft := ALeft; FTop := ATop; FWidth := AWidth; FHeight := AHeight; UpdateAnchorRules; Invalidate; Perform(WM_WINDOWPOSCHANGED, 0, 0); RequestAlign; if not (csLoading in ComponentState) then Resize; end; end;
忽然发现,InvalidateControl已经声明了部分无效区域,那么WM_PAINT会立即发过来运行吗?还是会继续往下运行FLeft := ALeft;语句和Invalidate语句?我的看法是,上面这些函数的代码都是连续执行的。WM_PAINT消息有可能在InvalidateControl语句之后、Invalidate语句之前已经发送到线程消息队列(但也仅仅是有可能,待验证),但它一定没有机会被程序取出来,因为当前程序正忙,没有机会调用run()函数里的消息循环。说到底,消息也是程序自己去取来的,而不是不请自到。所以也就不用担心WM_PAINT消息在函数的中间执行过程添乱,它没有这个机会。
即使SendMessage不走消息队列,而是直接调用WinProc函数,但那也是顺序执行语句。在单线程情况下,没到SendMessage语句,它就没有机会执行相关代码,没机会给别的代码添乱,也没有机会给自己的当前函数添乱。